if_ex.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:45k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* if_ex.c - Excelan EXOS 201/202/302 Ethernet network interface driver */
  2. /* Copyright 1984-1997 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1980, 1986 Regents of the University of California.
  6.  * All rights reserved.  The Berkeley software License Agreement
  7.  * specify the terms and conditions for redistribution.
  8.  *
  9.  *      @(#)if_ex.c     7.1 (Berkeley) 6/5/86
  10.  */
  11. /*
  12. modification history
  13. --------------------
  14. 03u,15jul97,spm  added ARP request to SIOCSIFADDR ioctl handler
  15. 03t,07apr97,spm  code cleanup, corrected statistics, and upgraded to BSD 4.4
  16. 03s,14oct93,wmd  Added use of ntohs macro to correct parameter passed in
  17.  do_protocol_with_type(), spr #2571.
  18. 03r,11aug93,jmm  Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h
  19. 03q,27apr93,jdi  restored '/' to beginning of line 1 (spr 2180).
  20. 03p,22feb93,jdi  documentation cleanup.
  21. 03o,28jan93,rfs  Reworked sequence within attach routine that gleans the
  22.                  Ethernet address from the exos board.  The reply message
  23.                  is now handled by the interrupt handler.  SPR #1931.
  24. 03n,14oct92,rfs  Added documentation.
  25. 03m,02oct92,rfs  Made multiple attach calls per unit return OK, not ERROR.
  26. 03l,30sep92,rfs  Gathered all shared memory areas into one area that is
  27.                  allocated from cache-safe memory.  The driver will abort if
  28.                  a cache-safe area cannot be provided.  Also brought the
  29.                  driver up to conventions used in the others, except I left in
  30.                  the outgoing mbuf queue, since the driver only uses one
  31.                  transmit buffer.
  32. 03k,09sep92,gae  documentation tweaks.
  33. 03j,04sep92,ccc  Added address modifier parameter to exattach() routine.
  34.                  Now uses sysBusToLocalAdrs() to convert base address.
  35. 03i,18jul92,smb  Changed errno.h to errnoLib.h.
  36. 03h,26may92,rrr  the tree shuffle
  37.                  -changed includes to have absolute path from h/
  38. 03g,04may92,elh  changed exInit to return 0 if running.  cleaned up
  39.                  some ansi warnings.
  40. 03f,22apr92,jwt  converted CPU==SPARC to CPU_FAMILY==SPARC; copyright.
  41. 03e,11nov91,jpb  fixed bug in exoutput status return path.
  42.                  disable data cache (currently SPARC only).
  43. 03d,04oct91,rrr  passed through the ansification filter
  44.                  -changed functions to ansi style
  45.                  -changed includes to have absolute path from h/
  46.                  -fixed #else and #endif
  47.                  -changed READ, WRITE and UPDATE to O_RDONLY O_WRONLY and O_RDWR
  48.                  -changed VOID to void
  49.                  -changed copyright notice
  50. 03c,13sep91,jpb  added argument to exattach to specify address modifier for
  51.                  DME access to memory.  Made exBusAdrsSpace local.
  52. 03b,29apr91,hdn  use SIZEOF_ETHERHEADER instead of sizeof(ether_header).
  53. 03a,10apr91,jdi  documentation cleanup; fixed comment block in exattach() that
  54.                  had effectively commented out declaration of ivec;
  55.                  doc review by elh.
  56. 02z,02oct90,hjb  made exinit() return int always.
  57. 02y,19sep90,dab  made exinit() return int.
  58. 02x,10aug90,dnw  added forward declarations of void routines.
  59.                  added include of if_subr.h.
  60. 02w,15jul90,dnw  coerced calloc() to (char*) where necessary
  61. 02v,11jul90,hjb  removed references to ipintr().  changed calls to do_protocol()
  62.                  to use do_protocol_with_type() instead.
  63. 02u,26jun90,hjb  copy_from_mbufs() & m_freem() fix
  64. 02t,02may90,gae  fixed EXOS 302 initialization of address modifier register.
  65.            +hjb  changed ETHERMIN+X to ETHERSMALL.  Turned off DEBUG.
  66.                  increased exconfig test delay from 5 secs.
  67. 02s,19apr90,hjb  deleted param.h, de-linted, modifications for
  68.                  copy_from_mbufs().
  69. 02r,18mar90,hjb  reduction of redundant code and addition of cluster support.
  70. 02q,07aug89,gae  SPARC cleanup.
  71.     07apr89,ecs  fixed references to unaligned structure in exhangrcv & exstart.
  72. 02p,29jul88,gae  fixed printf happening at interrupt level.
  73. 02o,30may88,dnw  changed to v4 names.
  74. 02n,28jan88,jcf  made kernel independent.
  75. 02m,05jan88,rdc  added include of systm.h
  76. 02l,20nov87,ecs  lint
  77.            &dnw  changed exattach to take int vec num instead of vec adrs.
  78. 02k,17nov87,dnw  fixed printing of transmit errors.
  79. 02j,03nov87,dnw  added vxTdelay(1) to init and configuration wait loops so that
  80.                  entire cpu (and in some cases entire bus!) isn't tied up.
  81.                  added global variable exBusAdrsSpace to allow modification
  82.                  of what address space excelan should use to address buffers.
  83.                  added output hook code.
  84.                  changed calling sequence to input hook.
  85.                  changed exreset to actually reset hardware.
  86. 02i,21oct87,ecs  delinted
  87. 02h,03may87,dnw  removed unnecessary includes.
  88.                  changed BUS_ADDR macro to exHostAdrs() routine
  89.                  which uses new call to sysLocalToBusAdrs().
  90.                  added input hook code.
  91. 02g,29apr87,dnw  changed exconfig() to set meaninfug status on error.
  92. 02f,08apr87,llk  enable interrupts from the excelan board with sysIntEnable.
  93. 02e,03apr87,ecs  added copyright.
  94. 02d,01apr87,jlf  delinted.
  95. 02c,20mar87,dnw  Added probe of excelan board and timeout of self-test
  96.                  in exconfig.
  97. 02b,14feb87,dnw  Formatted and cleaned up.
  98.                  Changed to keep array of ptrs to ex_softc structure
  99.                  and to dynamically allocate those structures as attached.
  100.                  Up to 10 controllers allowed.
  101.                  Fixed call to intConnect to pass unit to interrupt routine.
  102.                  Changed to use global sysBus, sysLocalToBusAdrs(), and
  103.                  sysIntAck(), instead of passing bus type, bus adrs offset,
  104.                  and ack address, respectively, to exattach().
  105. 02a,02feb87,jlf  Removed CLEAN ifdefs.
  106. 01c,30nov86,dnw  added exIntrAck kludge to ack ints for hkv2f.
  107.                  changed vmeOffset to exBusOffset.
  108. 01b,26nov86,llk  got rid of conditional compiles dependent on BUS.
  109.                  Added LOCAL varibles exBus and vmeOffset.
  110. 01a,31oct86,jlf  changed BUS_ADDR to mask out upper address bits
  111.                  added HK kludge.
  112. ... adapted from original Excelan interface by George Powers
  113. */
  114. /*
  115. This module implements the Excelan EXOS 201/202/302 Ethernet network
  116. interface driver.
  117. This driver is designed to be moderately generic, operating unmodified
  118. across the range of architectures and targets supported by VxWorks.
  119. To achieve this, the driver must be given several target-specific
  120. parameters.  These parameters, and the mechanisms used to communicate them
  121. to the driver, are detailed below.  This driver supports up to four
  122. individual units per CPU.
  123. All packet control information and data moves between the EXOS board and the
  124. target board in a shared memory region.  This shared memory must reside on the
  125. target board, since the EXOS board does not present any memory to the VME bus. Therefore, this driver will obtain an area of local memory, and assumes that
  126. this area of memory can be accessed from the VME bus.
  127. BOARD LAYOUT
  128. The diagram below shows the relevant jumpers for VxWorks configuration.
  129. Default values are: I/O address 0x00ff0000, Standard Addressing (A24),
  130. interrupt level 2.
  131. .bS
  132. ______________________________                                            _
  133. |             P1             | EXOS 202 OLD             NO P2!            |
  134. |                            |___________________________________________ |
  135. |:::XDDDU:::X:::::::X:::::X:                                              |
  136. |BGINBGOTBREQ IO ADRS INT LVL                                             |
  137. |                                                                         |
  138. |                                                                         |
  139. |                                                                         |
  140. |                                                                         |
  141. |                                                                         |
  142. |                                                                         |
  143. |                                                                         |
  144. |                                                                         |
  145. |                                                                         |
  146. |                                                                         |
  147. |                                  "                                      |
  148. |                                   X INT ACK                             |
  149. |                                   X                                     |
  150. |                                                                         |
  151. |                                                                         |
  152. |                                                                         |
  153. |                                                                         |
  154. |_________________________________________________________________________|
  155. .bE
  156. .bS
  157. ______________________________              _______________________________
  158. |             P1             | EXOS 202 NEW |             P2              |
  159. |                            ----------------                             |
  160. |:::::X UUUD :::X  :::::::X  :::::X:                                      |
  161. |BGIN   BGOT BREQ   IO ADRS  INT LVL                                      |
  162. |                                                                         |
  163. |                                                                         |
  164. |                                                                         |
  165. |                                                                         |
  166. |                                                                         |
  167. |                                                                         |
  168. |                                                                         |
  169. |                                                                         |
  170. |                                                                         |
  171. |                                                                         |
  172. |                                                                         |
  173. | -"-                                                                     |
  174. |                                                                         |
  175. | INT ACK                                                                 |
  176. |                                                                         |
  177. |                                                                         |
  178. |                                                                         |
  179. |_________________________________________________________________________|
  180. .bE
  181. .bS
  182. ______________________________              _______________________________
  183. |             P1             |   EXOS 302   |             P2              |
  184. |                            ----------------                             |
  185. |             :X:  :::::X:    :::::    ::::::::XXXXXXXX                   |
  186. |         INT ACK  INT LVL    *24/32 ADR   IO ADRS                        |
  187. |         J54-J56  J47-J53    J42-J46      J26-J41                        |
  188. |                                                                         |
  189. |                                                                         |
  190. |                                                                         |
  191. |                                                                         |
  192. |                                                                         |
  193. |                                                                         |
  194. |                                                                         |
  195. |                                                                         |
  196. |                                                                         |
  197. |                                                                         |
  198. |                                                                         |
  199. |                                                                         |
  200. |                                                                         |
  201. |         ::::::X:                                                        |
  202. |           SQE                       * remove J44 for A32 master mode    |
  203. |          J2-J9                      * remove J46 for A32 slave mode     |
  204. |_________________________________________________________________________|
  205. .bE
  206. EXTERNAL INTERFACE
  207. This driver provides the standard external interface with the following
  208. exceptions.  All initialization is performed within the attach routine;
  209. there is no separate initialization routine.  Therefore, in the global interface
  210. structure, the function pointer to the initialization routine is NULL.
  211. The only user-callable routine is exattach(), which publishes the `ex'
  212. interface and initializes the driver and device.
  213. TARGET-SPECIFIC PARAMETERS
  214. .iP "base VME address of EXOS I/O ports"
  215. This parameter is passed to the driver by exattach().
  216. The EXOS board presents a small set of I/O ports onto the VME bus.  This
  217. address is jumper selectable on the EXOS board.  This parameter is the
  218. same as the address selected on the EXOS board.
  219. .iP "VME address modifier code, EXOS access"
  220. This parameter is passed to the driver by exattach().
  221. It specifies the AM (address modifier) code to use when 
  222. the driver accesses the VME address space (ports) of the EXOS board.
  223. .iP "VME address modifier code, target access"
  224. This parameter is passed to the driver by exattach().
  225. It specifies the AM code that the EXOS board needs to use
  226. when it accesses the shared memory on the target board.
  227. .iP "interrupt vector"
  228. This parameter is passed to the driver by exattach().
  229. It specifies the interrupt vector to be used by the driver
  230. to service an interrupt from the EXOS board.  The driver connects
  231. the interrupt handler to this vector by calling intConnect().
  232. .iP "interrupt level"
  233. This parameter is passed to the driver by exattach().
  234. It specifies the interrupt level that is associated with the
  235. interrupt vector.  The driver enables the interrupt from the EXOS by
  236. calling sysIntEnable() with this parameter.
  237. .LP
  238. SYSTEM RESOURCE USAGE
  239. When implemented, this driver requires the following system resources:
  240.     - one interrupt vector
  241.     - 8 bytes in the initialized data section (data)
  242.     - 668 bytes in the uninitialized data section (BSS)
  243. The above data and BSS requirements are for the MC68020 architecture 
  244. and may vary for other architectures.  Code size (text) varies greatly between
  245. architectures and is therefore not quoted here.
  246. This driver uses cacheDmaMalloc() to allocate the memory to be shared 
  247. with the EXOS board.  The size requested is 3512 bytes.
  248. This driver can only be operated if this shared memory region is non-cacheable.
  249. The driver cannot maintain cache coherency for the shared memory because 
  250. asynchronous modifications by the EXOS board may share cache lines with
  251. locations being operated on by the driver.
  252. SEE ALSO: ifLib
  253. */
  254. #include "vxWorks.h"
  255. #include "vme.h"
  256. #include "net/mbuf.h"
  257. #include "net/protosw.h"
  258. #include "sys/socket.h"
  259. #include "sys/ioctl.h"
  260. #include "errnoLib.h"
  261. #include "iv.h"
  262. #include "memLib.h"
  263. #include "cacheLib.h"
  264. #include "net/if.h"
  265. #include "net/route.h"
  266. #ifdef  INET
  267. #include "netinet/in.h"
  268. #include "netinet/in_systm.h"
  269. #include "netinet/in_var.h"
  270. #include "netinet/ip.h"
  271. #include "netinet/if_ether.h"
  272. #endif  /* INET */
  273. #include "drv/netif/if_exreg.h"
  274. #include "sysLib.h"
  275. #include "wdLib.h"
  276. #include "iosLib.h"
  277. #include "intLib.h"
  278. #include "etherLib.h"
  279. #include "netLib.h"
  280. #include "stdlib.h"
  281. #include "stdio.h"
  282. #include "logLib.h"
  283. #include "vxLib.h"
  284. #include "net/systm.h"
  285. #include "net/if_subr.h"
  286. #include "net/unixLib.h"
  287. /***** LOCAL DEFINITIONS *****/
  288. #define EX_DEBUG                /* enable some debug checks and messages */
  289. #define MAX_UNITS  4            /* max number of EXOS controllers supported */
  290. #define NH2X    4               /* a sufficient number is critical */
  291. #define NX2H    1               /* this is pretty arbitrary */
  292. /* Typedefs for external structures that are not typedef'd in their .h files */
  293. typedef struct mbuf MBUF;
  294. typedef struct arpcom IDR;                  /* Interface Data Record wrapper */
  295. typedef struct ifnet IFNET;                 /* real Interface Data Record */
  296. typedef struct sockaddr SOCK;               /* generic socket address */
  297. typedef struct exdevice DEV_CTRL;           /* EXOS device control */
  298. typedef struct ex_msg EX_MSG;               /* an EXOS message */
  299. typedef struct confmsg CFG_MSG;             /* an EXOS configuration message */
  300. typedef struct stat_array STAT_ARRAY;       /* EXOS status area */
  301. #define EX_MSG_SIZ      sizeof(EX_MSG)
  302. #define CFG_MSG_SIZ     sizeof(CFG_MSG)
  303. #define STAT_ARRAY_SIZ  sizeof(STAT_ARRAY)
  304. /* The definition of the driver control structure */
  305. typedef struct drv_ctrl
  306.     {
  307.     IDR                 idr;            /* interface data record */
  308.     BOOL                attached;       /* indicates attach completed */
  309.     int                 ivec;           /* interrupt vector */
  310.     int                 ilevel;         /* interrupt level */
  311.     int                 flags;          /* private flags */
  312.     int                 shMemSize;      /* size of shared memory area */
  313.     caddr_t             pShMem;         /* pointer to shared memory area */
  314.     DEV_CTRL            *pDev;          /* device address */
  315.     EX_MSG              *pH2XNext;      /* host pointer to request queue */
  316.     EX_MSG              *pX2HNext;      /* host pointer to reply queue */
  317.     /* Pointers to shared memory members.
  318.      * These are static after initialization.
  319.      */
  320.     CFG_MSG             *pCfgMsg;       /* configuration message */
  321.     STAT_ARRAY          *pStatArray;    /* EXOS writes stats here */
  322.     u_short             *pH2XHdr;       /* ptr to EXOS' host outgoing header */
  323.     u_short             *pX2HHdr;       /* ptr toEXOS' host incoming header */
  324.     EX_MSG              *pH2XQueue;     /* request msg buffers */
  325.     EX_MSG              *pX2HQueue;     /* reply msg buffers */
  326.     caddr_t             pWriteBuf;      /* pointer to write buffer */
  327.     caddr_t             pReadBuf;       /* pointer to read buffer */
  328.     } DRV_CTRL;
  329. /* Some values for the flags */
  330. #define EX_XPENDING     1                   /* xmit rqst pending on EXOS */
  331. #define EX_STATPENDING  (1<<1)              /* stats rqst pending on EXOS */
  332. #define EX_RUNNING      (1<<2)              /* board is running */
  333. #define EX_SETADDR      (1<<3)              /* physaddr has been changed */
  334. /***** GLOBALS *****/
  335. /***** LOCALS *****/
  336. /* The array of driver control structures, one per unit supported */
  337. LOCAL DRV_CTRL drvCtrl [MAX_UNITS];
  338. #undef EX_RESET
  339. LOCAL int EX_RESET = 0; /* because using constant causes "clr" inst. */
  340. LOCAL BOOL exBit32 = FALSE;     /* TRUE = in VME extended address space */
  341. /*
  342.  * VME address space that the EXOS should use to access host buffers, etc.
  343.  * This is normally standard space but can be changed through the exattach
  344.  * argument (exDmaAm).
  345.  */
  346. LOCAL int exBusAdrsSpace;
  347. /* forward static functions */
  348. static void exReset (int unit);
  349. static STATUS exConfig (int unit, int itype);
  350. #ifdef BSD43_DRIVER
  351. static void exStart (int unit);
  352. #else
  353. static void exStart (DRV_CTRL *pDrvCtrl);
  354. #endif
  355. static void exIntr (int unit);
  356. static EX_MSG *exMsgBlkGet (DRV_CTRL *pDrvCtrl);
  357. static void exRecvAndHang (int unit, int len, int status);
  358. static void exRecv (int unit, int len, int status);
  359. static void exRxRqst (int unit);
  360. #ifdef BSD43_DRIVER
  361. static int exOutput (IDR *pIDR, MBUF *pMbuf, SOCK *pDest);
  362. #endif
  363. static int exIoctl (IDR *pIDR, int cmd, caddr_t data);
  364. static char *exHostAdrs (char *localAdrs);
  365. static void exGiveRequest (EX_MSG *pMsg, DEV_CTRL *pDev);
  366. /*******************************************************************************
  367. *
  368. * exattach - publish the `ex' network interface and initialize the driver and device
  369. *
  370. * This routine publishes the `ex' interface by filling in a network 
  371. * interface record and adding this record to the system list.  It also
  372. * initializes the driver and the device to the operational state.
  373. *
  374. * RETURNS: OK or ERROR.
  375. */
  376. STATUS exattach
  377.     (
  378.     int unit,           /* logical number of this interface */
  379.     char *pDev,         /* bus address of EXOS device ports */
  380.     int ivec,           /* interrupt vector */
  381.     int ilevel,         /* interrupt level */
  382.     int exDmaAm,        /* VME addr modifier to access CPU memory */
  383.     int exAdrsAm        /* VME addr modifier to access EXOS ports */
  384.     )
  385.     {
  386.     int             loopy;
  387.     STATUS          ret;                /* return value of called funcs */
  388.     EX_MSG          *pMsg;
  389.     DRV_CTRL        *pDrvCtrl;
  390.     /* Sanity check the unit number */
  391.     if (unit < 0 || unit >= MAX_UNITS)
  392.         return (ERROR);
  393.     /* Ensure single invocation per system life */
  394.     pDrvCtrl = & drvCtrl [unit];
  395.     if (pDrvCtrl->attached)
  396.         return (OK);
  397.     /* Save some parms */
  398.     pDrvCtrl->ivec  = ivec;
  399.     pDrvCtrl->ilevel= ilevel;
  400.     /* Convert the buss address of the EXOS board's registers to the local
  401.      * address to use for the specified address space.
  402.      */
  403.     if  (
  404.         sysBusToLocalAdrs (exAdrsAm, pDev, (char **) & pDrvCtrl->pDev)
  405.         == ERROR
  406.         )
  407.         return (ERROR);
  408.     /* Publish the interface data record */
  409. #ifdef BSD43_DRIVER
  410.     ether_attach (&pDrvCtrl->idr.ac_if, unit, "ex", (FUNCPTR) NULL,
  411.                   (FUNCPTR) exIoctl, (FUNCPTR) exOutput, (FUNCPTR) exReset);
  412. #else
  413.     ether_attach (
  414.                  &pDrvCtrl->idr.ac_if, 
  415.                  unit, 
  416.                  "ex", 
  417.                  (FUNCPTR) NULL,
  418.                  (FUNCPTR) exIoctl, 
  419.                  ether_output, 
  420.                  (FUNCPTR) exReset
  421.                  );
  422.     pDrvCtrl->idr.ac_if.if_start = (FUNCPTR)exStart;
  423. #endif
  424.     /* setup address modifier */
  425.     if  (
  426.         (VME_AM_EXT_USR_DATA <= exDmaAm) &&
  427.         (exDmaAm <= VME_AM_STD_SUP_ASCENDING)
  428.         )
  429.         exBusAdrsSpace = exDmaAm;
  430.     else
  431.         exBusAdrsSpace = VME_AM_STD_SUP_DATA;
  432.     exBit32 = VME_AM_IS_EXT(exBusAdrsSpace);
  433.     { /***** Obtain memory area that will be shared with the EXOS board *****/
  434.     /* this driver can't handle incoherent caches */
  435.     if ( !CACHE_DMA_IS_WRITE_COHERENT () || !CACHE_DMA_IS_READ_COHERENT () )
  436.         {
  437.         printErr ( "nex%d: requires cache coherent memoryn", unit );
  438.         return (ERROR);
  439.         }
  440.     pDrvCtrl->shMemSize =
  441.                 CFG_MSG_SIZ +               /* the config message */
  442.                 STAT_ARRAY_SIZ +            /* the status array */
  443.                                             /* the EXOS firmware headers */
  444.                 sizeof (*pDrvCtrl->pH2XHdr) +
  445.                 sizeof (*pDrvCtrl->pX2HHdr) +
  446.                 (EX_MSG_SIZ * NH2X) +       /* outbound message queue */
  447.                 (EX_MSG_SIZ * NX2H) +       /*  inbound message queue */
  448.                 EXMAXRBUF +                 /* one packet write buffer */
  449.                 EXMAXRBUF +                 /* one packet read buffer */
  450.                 16;                         /* to allow alignment */
  451.     /* Attempt to get cache coherent memory */
  452.     pDrvCtrl->pShMem = cacheDmaMalloc (pDrvCtrl->shMemSize);
  453.     if ( pDrvCtrl->pShMem == NULL )
  454.         {
  455. #ifdef EX_DEBUG
  456.         printErr ( "nex%d: no memory availablen", unit );
  457. #endif
  458.         return ( ERROR );
  459.         }
  460.     /* Clear the whole block */
  461.     bzero (pDrvCtrl->pShMem, pDrvCtrl->shMemSize);
  462.     } /* Block end */
  463.     { /***** Carve up the shared memory *****/
  464.     caddr_t pCur;                   /* pointer to current location */
  465.     pCur = pDrvCtrl->pShMem;        /* start at location assigned above */
  466.     pCur = (caddr_t) ((int)pCur + 15);   /* bump up to next 16 byte page */
  467.     pCur = (caddr_t) ((int) pCur & ~0xf);
  468.     /* This 16-byte-page aligned address is used as the base address of the
  469.      * shared memory area.  This base address is used in offset calculations
  470.      * for various values communicated to the EXOS firmware.  The config
  471.      * message starts at this base address, and can therefore be used as an
  472.      * alias.
  473.      */
  474.     pDrvCtrl->pCfgMsg = (CFG_MSG *) pCur;
  475.     pCur = (caddr_t)((int)pCur + CFG_MSG_SIZ);
  476.     pDrvCtrl->pStatArray = (STAT_ARRAY *) pCur;
  477.     pCur = (caddr_t)((int)pCur + STAT_ARRAY_SIZ);
  478.     pDrvCtrl->pH2XHdr = (u_short *) pCur;
  479.     pCur = (caddr_t)((int)pCur + sizeof (*pDrvCtrl->pH2XHdr));
  480.     pDrvCtrl->pX2HHdr = (u_short *) pCur;
  481.     pCur = (caddr_t)((int)pCur + sizeof (*pDrvCtrl->pX2HHdr));
  482.     pDrvCtrl->pH2XQueue = (EX_MSG *) pCur;
  483.     pCur = (caddr_t)((int)pCur + (EX_MSG_SIZ * NH2X));
  484.     pDrvCtrl->pX2HQueue = (EX_MSG *) pCur;
  485.     pCur = (caddr_t)((int)pCur + (EX_MSG_SIZ * NX2H));
  486.     pDrvCtrl->pWriteBuf = pCur;
  487.     pCur = (caddr_t)((int)pCur + EXMAXRBUF);
  488.     pDrvCtrl->pReadBuf = pCur;
  489.     } /* Block end */
  490.     { /***** Initialize the message queues and headers *****/
  491.     int     base;
  492.     u_short offset;
  493.     /* The offset of certain objects from a base address is a common theme
  494.      * in the shared data.  The config message happens to start at the base
  495.      * address of the shared memory region, so we cast it and store it as an
  496.      * integer once, to make the multiple uses easier to read.
  497.      */
  498.     base = (int) pDrvCtrl->pCfgMsg;
  499.     /* First the request queue (host-to-EXOS) */
  500.     pMsg = pDrvCtrl->pH2XQueue;
  501.     for ( loopy = NH2X; loopy--; )
  502.         {
  503.         /* The link is the offset of the next message from the base of
  504.          * the shared memory area.
  505.          */
  506.         offset          = (u_short) ((int)(pMsg+1) - base);
  507.         pMsg->mb_link     = offset;
  508.         pMsg->mb_rsrv     = 0;
  509.         pMsg->mb_length   = MBDATALEN;
  510.         pMsg->mb_status   = MH_HOST;            /* we own it */
  511.         pMsg->mb_next     = pMsg+1;             /* our ptr to next */
  512.         pMsg++;
  513.         }
  514.     /* Fix up the last message to point back at first message */
  515.     pMsg--;
  516.     offset = (u_short) ((int)pDrvCtrl->pH2XQueue - base);
  517.     pMsg->mb_link = offset;
  518.     pMsg->mb_next = pDrvCtrl->pH2XQueue;
  519.     /* Initialize the variables that indicate the next message.
  520.      * Ours is a direct pointer, while the EXOS firmware uses an offset.
  521.      */
  522.     *pDrvCtrl->pH2XHdr = offset;
  523.     pDrvCtrl->pH2XNext = pDrvCtrl->pH2XQueue;
  524.     /* Now the reply queue (EXOS-to-host) */
  525.     pMsg = pDrvCtrl->pX2HQueue;
  526.     for ( loopy = NX2H; loopy--; )
  527.         {
  528.         /* The link is the offset of the next message from the base of
  529.          * the shared memory area.
  530.          */
  531.         offset            = (u_short) ((int)(pMsg+1) - base);
  532.         pMsg->mb_link     = offset;
  533.         pMsg->mb_rsrv     = 0;
  534.         pMsg->mb_length   = MBDATALEN;
  535.         pMsg->mb_status   = MH_EXOS;            /* EXOS owns it */
  536.         pMsg->mb_next     = pMsg+1;             /* our ptr to next */
  537.         pMsg++;
  538.         }
  539.     /* Fix up the last message to point back at first message */
  540.     pMsg--;
  541.     offset = (u_short) ((int)pDrvCtrl->pX2HQueue - base);
  542.     pMsg->mb_link = offset;
  543.     pMsg->mb_next = pDrvCtrl->pX2HQueue;
  544.     /* Initialize the variables that indicate the next message.
  545.      * Ours is a direct pointer, while the EXOS firmware uses an offset.
  546.      */
  547.     *pDrvCtrl->pX2HHdr = offset;
  548.     pDrvCtrl->pX2HNext = pDrvCtrl->pX2HQueue;
  549.     } /* Block end */
  550.     /* Configure the board */
  551.     if (sysBus == VME_BUS)
  552.         ret = exConfig (unit, 4);              /* with vectored interrupts */
  553.     else
  554.         ret = exConfig (unit, 3);              /* with level interrupts */
  555.     if (ret != OK)
  556.         return (ERROR);
  557.     /* Connect interrupt handler, enable interrupt */
  558.     (void) intConnect (INUM_TO_IVEC (ivec), exIntr, unit);
  559.     (void) sysIntEnable (ilevel);
  560.     /* Ask the board for its physical Ethernet address.  The reply will be
  561.      * processed by the interrupt handler.  We wait for the handler to complete
  562.      * by using the ethernet address field as a sync flag: it will be zero
  563.      * until filled in by the reply processing.
  564.      */
  565.     pMsg = exMsgBlkGet (pDrvCtrl);
  566.     pMsg->mb_rqst       = LLNET_ADDRS;
  567.     pMsg->mb_na.na_mask = READ_OBJ;
  568.     pMsg->mb_na.na_slot = PHYSSLOT;
  569.     exGiveRequest (pMsg, pDrvCtrl->pDev);
  570.     for ( loopy = 10; ; loopy-- )
  571.         {
  572.         taskDelay (10);
  573.         if ( *(long *)pDrvCtrl->idr.ac_enaddr )  /* check 'sync flag' */
  574.             break;
  575.         if ( loopy < 0 )                      /* if reached retry limit */
  576.             return (ERROR);
  577.         }
  578.     /* Enable the EXOS board onto the Ethernet, using NET_MODE command */
  579.     pMsg = exMsgBlkGet (pDrvCtrl);
  580.     pMsg->mb_rqst       = LLNET_MODE;
  581.     pMsg->mb_nm.nm_mask = WRITE_OBJ;
  582.     pMsg->mb_nm.nm_optn = 0;
  583.     pMsg->mb_nm.nm_mode = MODE_PERF;
  584.     exGiveRequest (pMsg, pDrvCtrl->pDev);
  585.     exRxRqst (unit);                   /* post a receive request */
  586.     /* Set flags */
  587.     pDrvCtrl->attached = TRUE;
  588.     pDrvCtrl->idr.ac_if.if_flags |= ( IFF_RUNNING | IFF_UP | IFF_NOTRAILERS );
  589.     pDrvCtrl->flags = EX_RUNNING;
  590.     return (OK);
  591.     }
  592. /*******************************************************************************
  593. *
  594. * exReset - reset the EXOS board and bring down interface
  595. */
  596. LOCAL void exReset
  597.     (
  598.     int unit
  599.     )
  600.     {
  601.     int temp;
  602.     DRV_CTRL *pDrvCtrl;
  603.     /* Sanity check the unit number */
  604.     if (unit < 0 || unit >= MAX_UNITS)
  605.         return;
  606.     pDrvCtrl = & drvCtrl [unit];
  607.     pDrvCtrl->idr.ac_if.if_flags = 0;
  608.     pDrvCtrl->flags &= ~EX_RUNNING;
  609.     if (sysBus == VME_BUS)
  610.         pDrvCtrl->pDev->bus.vme.xd_porta = EX_RESET;
  611.     else
  612.         temp = pDrvCtrl->pDev->bus.multi.xd_porta;    /* access location */
  613.     }
  614. /*******************************************************************************
  615. *
  616. * exConfig - configure EXOS board
  617. *
  618. * Reset, test, and configure EXOS.
  619. */
  620. LOCAL STATUS exConfig
  621.     (
  622.     int unit,
  623.     int itype                       /* interrupt type */
  624.     )
  625.     {
  626.     char            val;           /* sizeof xd_porta */
  627.     int             ix;
  628.     u_long          shiftreg;
  629.     DRV_CTRL        *pDrvCtrl;
  630.     DEV_CTRL        *pDev;
  631.     CFG_MSG         *pCfgMsg;
  632.     pDrvCtrl = & drvCtrl [unit];
  633.     pDev     = pDrvCtrl->pDev;
  634.     pCfgMsg  = pDrvCtrl->pCfgMsg;
  635.    /* Reset EXOS via probe (in case board doesn't exist) */
  636.     if (sysBus == VME_BUS)
  637.         {
  638.         val = EX_RESET;
  639.         if (vxMemProbe ((char *)&pDev->bus.vme.xd_porta, O_WRONLY,
  640.                         sizeof (pDev->bus.vme.xd_porta), &val) == ERROR)
  641.             {
  642.             errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT);
  643.             return (ERROR);
  644.             }
  645.         }
  646.     else
  647.         {
  648.         if (vxMemProbe ((char *)&pDev->bus.multi.xd_porta, O_RDONLY,
  649.                         sizeof (pDev->bus.multi.xd_porta), &val) == ERROR)
  650.             {
  651.             errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT);
  652.             return (ERROR);
  653.             }
  654.         }
  655.     /* wait for test to complete (10 secs max) */
  656.     for (ix = 10 * sysClkRateGet (); ix > 0; ix--)
  657.         {
  658.         if (sysBus == VME_BUS)
  659.             {
  660.             if ((pDev->bus.vme.xd_portb & EX_TESTOK) != 0)
  661.                 break;
  662.             }
  663.           else
  664.             {
  665.             if ((pDev->bus.multi.xd_portb & EX_TESTOK) != 0)
  666.                 break;
  667.             }
  668.         taskDelay (1);
  669.         }
  670.     if (ix == 0)
  671.         {
  672. #ifdef EX_DEBUG
  673.         printErr ("ex%d: self-test failed.n", unit);
  674. #endif
  675.         errnoSet (S_ioLib_DEVICE_ERROR);
  676.         return (ERROR);
  677.         }
  678.     /* Write address modifier to Port C on EXOS 302 (after reset). */
  679.     if (sysBus == VME_BUS && exBit32)
  680.         pDrvCtrl->pDev->bus.vme.xd_portc = exBusAdrsSpace;
  681.     /* Set up configuration message. */
  682.     pCfgMsg->cm_1rsrv       = 1;
  683.     pCfgMsg->cm_cc          = 0xFF;
  684.     pCfgMsg->cm_opmode      = 0;        /* link-level controller mode */
  685.     pCfgMsg->cm_dfo         = 0x0101;   /* enable host data order conversion */
  686.     pCfgMsg->cm_dcn1        = 1;
  687.     pCfgMsg->cm_2rsrv[0]    = 0;
  688.     pCfgMsg->cm_2rsrv[1]    = 0;
  689.     pCfgMsg->cm_ham         = 3;          /* absolute address mode */
  690.     pCfgMsg->cm_3rsrv       = 0;
  691.     pCfgMsg->cm_mapsiz      = 0;
  692.     pCfgMsg->cm_byteptrn[0] = 0x01;       /* EXOS deduces data order of host */
  693.     pCfgMsg->cm_byteptrn[1] = 0x03;       /*  by looking at this pattern */
  694.     pCfgMsg->cm_byteptrn[2] = 0x07;
  695.     pCfgMsg->cm_byteptrn[3] = 0x0F;
  696.     pCfgMsg->cm_wordptrn[0] = 0x0103;
  697.     pCfgMsg->cm_wordptrn[1] = 0x070F;
  698.     pCfgMsg->cm_lwordptrn   = 0x0103070F;
  699.     for (ix = 0; ix < 20; ix++)
  700.         pCfgMsg->cm_rsrvd[ix] = 0;
  701.     pCfgMsg->cm_mba         = 0xFFFFFFFF;
  702.     pCfgMsg->cm_nproc       = 0xFF;
  703.     pCfgMsg->cm_nmbox       = 0xFF;
  704.     pCfgMsg->cm_nmcast      = 0xFF;
  705.     pCfgMsg->cm_nhost       = 1;
  706.     pCfgMsg->cm_h2xba       = (u_long) exHostAdrs ( (char *) pCfgMsg );
  707.     pCfgMsg->cm_h2xhdr      = (u_short)
  708.                               ( (int)(pDrvCtrl->pH2XHdr) - (int)pCfgMsg );
  709.     pCfgMsg->cm_h2xtyp      = 0;        /* should never wait for rqst buffer */
  710.     pCfgMsg->cm_x2hba       = pCfgMsg->cm_h2xba;
  711.     pCfgMsg->cm_x2hhdr      = (u_short)
  712.                               ( (int)(pDrvCtrl->pX2HHdr) - (int)pCfgMsg );
  713.     pCfgMsg->cm_x2htyp      = itype;         /* 0=none, 4=vectored, 3=level */
  714.     if (sysBus == VME_BUS)
  715.         pCfgMsg->cm_x2haddr = pDrvCtrl->ivec;
  716.     /*
  717.      * Write config msg address to EXOS and wait for
  718.      * configuration to complete (guaranteed response within 2 seconds).
  719.      */
  720.     shiftreg = (u_long)0x0000FFFF;
  721.     for (ix = 0; ix < 8; ix++)
  722.         {
  723.         if (ix == 4)
  724.             shiftreg = (u_long) exHostAdrs ((char *)pCfgMsg);
  725.         if (sysBus == VME_BUS)
  726.             {
  727.             while (pDev->bus.vme.xd_portb & EX_UNREADY)
  728.                 ;
  729.             pDev->bus.vme.xd_portb = (u_char)(shiftreg & 0xFF);
  730.             }
  731.         else
  732.             {
  733.             while (pDev->bus.multi.xd_portb & EX_UNREADY)
  734.                 ;
  735.             pDev->bus.multi.xd_portb = (u_char)(shiftreg & 0xFF);
  736.             }
  737.         shiftreg >>= 8;
  738.         }
  739.     for (ix = 3 * sysClkRateGet (); (pCfgMsg->cm_cc == 0xFF) && ix; --ix)
  740.         taskDelay (1);
  741.     if (pCfgMsg->cm_cc)
  742.         {
  743. #ifdef EX_DEBUG
  744.         printErr    (
  745.                     "ex%d: configuration failed; cc=0x%xn",
  746.                     unit,
  747.                     pCfgMsg->cm_cc
  748.                     );
  749. #endif
  750.         errnoSet (S_ioLib_DEVICE_ERROR);
  751.         return (ERROR);
  752.         }
  753.     return (OK);
  754.     }
  755. /*******************************************************************************
  756. *
  757. * exStart - start or re-start output on interface
  758. *
  759. * Get another datagram to send off of the interface queue,
  760. * and map it to the interface before starting the output.
  761. * This routine is called by exOutput(), and exIntr().
  762. * In all cases, interrupts by EXOS are disabled.
  763. */
  764. #ifdef BSD43_DRIVER
  765. LOCAL void exStart
  766.     (
  767.     int unit
  768.     )
  769.     {
  770.     DRV_CTRL        *pDrvCtrl;
  771. #else
  772. LOCAL void exStart
  773.     (
  774.     DRV_CTRL *  pDrvCtrl
  775.     )
  776.     {
  777. #endif
  778.     EX_MSG          *pMsg;
  779.     MBUF            *pMbuf;
  780.     int             len;
  781.     int             s;
  782. #ifdef BSD43_DRIVER
  783.     pDrvCtrl = & drvCtrl [unit];
  784. #endif
  785.     s = splnet ();
  786.     if ((pDrvCtrl->flags & EX_XPENDING) == 0
  787.         && pDrvCtrl->idr.ac_if.if_snd.ifq_head != NULL)
  788.         {
  789.         IF_DEQUEUE(&pDrvCtrl->idr.ac_if.if_snd, pMbuf);
  790.         /* copy packet to write buffer */
  791.         copy_from_mbufs (pDrvCtrl->pWriteBuf, pMbuf, len);
  792.         /* Adjust length to ensure minimum packet size */
  793.         len = max (ETHERSMALL, len);
  794.         /* Place a transmit request. */
  795. #if (CPU_FAMILY == SPARC)
  796.         {
  797.         ULONG blockAddr;
  798.         pMsg = exMsgBlkGet (pDrvCtrl);
  799.         pMsg->mb_rqst                 = LLRTRANSMIT;
  800.         pMsg->mb_et.et_nblock         = 1;
  801.         pMsg->mb_et.et_blks[0].bb_len = (u_short)len;
  802.         blockAddr = (ULONG) exHostAdrs ((char *) pDrvCtrl->pWriteBuf);
  803.         pMsg->mb_et.et_blks[0].bb_addr[0] = blockAddr >> 16;
  804.         pMsg->mb_et.et_blks[0].bb_addr[1] = blockAddr & 0xffff;
  805.         }
  806. #else   /* CPU_FAMILY == SPARC */
  807.         pMsg = exMsgBlkGet (pDrvCtrl);
  808.         pMsg->mb_rqst                 = LLRTRANSMIT;
  809.         pMsg->mb_et.et_nblock         = 1;
  810.         pMsg->mb_et.et_blks[0].bb_len = (u_short)len;
  811.         *(char **)pMsg->mb_et.et_blks[0].bb_addr =
  812.                      exHostAdrs ((char *) pDrvCtrl->pWriteBuf);
  813. #endif  /* CPU_FAMILY == SPARC */
  814.         pDrvCtrl->flags |= EX_XPENDING;    /* indicate that xmit in progress */
  815.         exGiveRequest (pMsg, pDrvCtrl->pDev);
  816. #ifndef BSD43_DRIVER    /* BSD 4.4 ether_output() doesn't bump statistic. */
  817.         pDrvCtrl->idr.ac_if.if_opackets++;
  818. #endif
  819.         }
  820.     splx (s);
  821.     }
  822. /*******************************************************************************
  823. *
  824. * exIntr - interrupt handler
  825. *
  826. * This routine is called at interrupt level in response to an interrupt from
  827. * the controller.
  828. */
  829. LOCAL void exIntr
  830.     (
  831.     int unit
  832.     )
  833.     {
  834.     DRV_CTRL        *pDrvCtrl;
  835.     EX_MSG          *pMsg;
  836.     pDrvCtrl = & drvCtrl [unit];
  837.     pMsg = pDrvCtrl->pX2HNext;
  838.     sysBusIntAck (pDrvCtrl->ilevel);  /* acknowledge interrupt */
  839.     while ((pMsg->mb_status & MH_OWNER) == MH_HOST)
  840.         {
  841.         switch (pMsg->mb_rqst)
  842.             {
  843.             case LLRECEIVE:
  844.                 (void) netJobAdd    (
  845.                                     (FUNCPTR) exRecvAndHang,
  846.                                     unit,
  847.                                     pMsg->mb_er.er_blks[0].bb_len,
  848.                                     pMsg->mb_rply,
  849.                                     0,
  850.                                     0
  851.                                     );
  852.                 break;
  853.             case LLRTRANSMIT:
  854. #ifdef EX_DEBUG
  855.                 if ((pDrvCtrl->flags & EX_XPENDING) == 0)
  856.                     panic ("exxmit: no xmit pending");
  857. #endif  /* EX_DEBUG */
  858.                 pDrvCtrl->flags &= ~EX_XPENDING;
  859.                 if (pMsg->mb_rply == LL_OK)
  860.                     ;
  861.                 else if (pMsg->mb_rply & LLXM_1RTRY)
  862.                     {
  863.                     pDrvCtrl->idr.ac_if.if_collisions++;
  864.                     }
  865.                 else if (pMsg->mb_rply & LLXM_RTRYS)
  866.                     {
  867.                     pDrvCtrl->idr.ac_if.if_collisions += 2;       /* guess */
  868.                     }
  869.                 else if (pMsg->mb_rply & LLXM_ERROR)
  870.                     {
  871.                     pDrvCtrl->idr.ac_if.if_oerrors++;
  872.                     pDrvCtrl->idr.ac_if.if_opackets--;
  873. #ifdef EX_DEBUG
  874.                     logMsg ("ex%d: transmit error=%#xn", unit, pMsg->mb_rply,
  875.                             0, 0, 0, 0);
  876. #endif
  877.                     }
  878.                 if (pDrvCtrl->idr.ac_if.if_snd.ifq_head != NULL)
  879. #ifdef BSD43_DRIVER
  880.                     (void)netJobAdd ( (FUNCPTR)exStart, unit, 0, 0, 0, 0);
  881. #else
  882.                     (void)netJobAdd ( (FUNCPTR)exStart, (int)pDrvCtrl, 
  883.                                       0, 0, 0, 0);
  884. #endif
  885.                 break;
  886.             case LLNET_STSTCS:
  887.                 pDrvCtrl->idr.ac_if.if_ierrors = pDrvCtrl->pStatArray->sa_crc;
  888.                 pDrvCtrl->flags &= ~EX_STATPENDING;
  889.                 break;
  890.             case LLNET_ADDRS:
  891.                 /* Copy the enet addr from the message to our IDR */
  892.                 bcopy   (
  893.                         (caddr_t) pMsg->mb_na.na_addrs,
  894.                         (caddr_t) pDrvCtrl->idr.ac_enaddr,
  895.                         sizeof (pDrvCtrl->idr.ac_enaddr)
  896.                         );
  897.                 break;
  898.             case LLNET_RECV:
  899.             case LLNET_MODE:
  900.                 break;
  901.             }
  902.         if (sysBus == MULTI_BUS)
  903.             pDrvCtrl->pDev->bus.multi.xd_porta = 7;  /* ack the interrupt */
  904.         pMsg->mb_length = MBDATALEN;
  905.         exGiveRequest (pMsg, pDrvCtrl->pDev);
  906.         pMsg = pDrvCtrl->pX2HNext = pDrvCtrl->pX2HNext->mb_next;
  907.         }
  908.     }
  909. /*******************************************************************************
  910. *
  911. * exMsgBlkGet - get a request buffer
  912. *
  913. * Fill in standard values, advance pointer.
  914. */
  915. LOCAL EX_MSG *exMsgBlkGet
  916.     (
  917.     DRV_CTRL *pDrvCtrl
  918.     )
  919.     {
  920.     EX_MSG *pMsg;
  921.     pMsg = pDrvCtrl->pH2XNext;
  922. #ifdef EX_DEBUG
  923.     if ((pMsg->mb_status & MH_OWNER) == MH_EXOS)
  924.         panic ("ex: EXOS owns message buffer");
  925. #endif  /* EX_DEBUG */
  926.     pMsg->mb_1rsrv  = 0;
  927.     pMsg->mb_length = MBDATALEN;
  928.     pDrvCtrl->pH2XNext = pDrvCtrl->pH2XNext->mb_next;
  929.     return (pMsg);
  930.     }
  931. /*******************************************************************************
  932. *
  933. * exRecvAndHang - receive packet and post another receive request
  934. */
  935. LOCAL void exRecvAndHang
  936.     (
  937.     int unit,
  938.     int len,
  939.     int status
  940.     )
  941.     {
  942.     exRecv (unit, len, status);
  943.     exRxRqst (unit);
  944.     }
  945. /*******************************************************************************
  946. *
  947. * exRecv - process Ethernet receive completion
  948. *
  949. * If input error just drop packet.
  950. * Otherwise purge input buffered data path and examine
  951. * packet to determine type.  If can't determine length
  952. * from type, then have to drop packet.  Otherwise decapsulate
  953. * packet based on type and pass to type-specific higher-level
  954. * input routine.
  955. */
  956. LOCAL void exRecv
  957.     (
  958.     int unit,
  959.     int len,
  960.     int status
  961.     )
  962.     {
  963.     DRV_CTRL            *pDrvCtrl;
  964.     struct ether_header *eh;
  965.     MBUF                *pMbuf;
  966.     u_char              *pData;
  967.     pDrvCtrl = & drvCtrl [unit];
  968.     if (status != LL_OK)
  969.         {
  970.         pDrvCtrl->idr.ac_if.if_ierrors++;
  971. #ifdef EX_DEBUG
  972.         printErr ("ex%d: receive error=%bn", unit, status, RECV_BITS);
  973. #endif
  974.         return;
  975.         }
  976.     /* get input packet length and ptr to packet */
  977.     len -= 4;                                       /* subtract FCS */
  978.     eh = (struct ether_header *)(pDrvCtrl->pReadBuf);
  979.     pDrvCtrl->idr.ac_if.if_ipackets++;
  980.     /* call input hook if any */
  981.     if ( etherInputHookRtn != NULL )
  982.         {
  983.         if ( (* etherInputHookRtn)(&pDrvCtrl->idr.ac_if, (char *) eh, len) )
  984.             return; /* input hook has already processed this packet */
  985.         }
  986.     /* Subtract header size from length */
  987.     len -= SIZEOF_ETHERHEADER;
  988.     /* Get pointer to packet data */
  989.     pData = ((u_char *) eh) + (SIZEOF_ETHERHEADER);
  990.     pMbuf = copy_to_mbufs (pData, len, 0, & pDrvCtrl->idr.ac_if);
  991.     if (pMbuf == NULL)                  /* no room at the inn */
  992.         {
  993.         pDrvCtrl->idr.ac_if.if_ierrors++;
  994.         return;
  995.         }
  996. #ifdef BSD43_DRIVER
  997.     do_protocol_with_type (ntohs(eh->ether_type), pMbuf, &pDrvCtrl->idr, len);
  998. #else
  999.     do_protocol (eh, pMbuf, &pDrvCtrl->idr, len);
  1000. #endif
  1001.     }
  1002. /*******************************************************************************
  1003. *
  1004. * exRxRqst - send receive request to EXOS
  1005. *
  1006. * Called by exIntr, with interrupts disabled in both cases.
  1007. */
  1008. LOCAL void exRxRqst
  1009.     (
  1010.     int unit
  1011.     )
  1012.     {
  1013.     DRV_CTRL        *pDrvCtrl;
  1014.     EX_MSG          *pMsg;
  1015.     pDrvCtrl = & drvCtrl [unit];
  1016.     pMsg = exMsgBlkGet(pDrvCtrl);
  1017.     pMsg->mb_rqst                  = LLRECEIVE;
  1018.     pMsg->mb_er.er_nblock          = 1;
  1019.     pMsg->mb_er.er_blks[0].bb_len  = EXMAXRBUF;
  1020. #if     (CPU_FAMILY == SPARC)
  1021.     {
  1022.     ULONG blockAddr;
  1023.     blockAddr = (ULONG) exHostAdrs ((char *) pDrvCtrl->pReadBuf);
  1024.     pMsg->mb_er.er_blks[0].bb_addr[0] = blockAddr >> 16;
  1025.     pMsg->mb_er.er_blks[0].bb_addr[1] = blockAddr & 0xffff;
  1026.     }
  1027. #else
  1028.     *(char **)pMsg->mb_er.er_blks[0].bb_addr =
  1029.                     exHostAdrs ((char *) pDrvCtrl->pReadBuf);
  1030. #endif  /* CPU_FAMILY == SPARC */
  1031.     exGiveRequest (pMsg, pDrvCtrl->pDev);
  1032.     }
  1033. #ifdef BSD43_DRIVER
  1034. /*******************************************************************************
  1035. *
  1036. * exOutput - the output routine
  1037. */
  1038. LOCAL int exOutput
  1039.     (
  1040.     IDR *pIDR,
  1041.     MBUF *pMbuf,
  1042.     SOCK *pDest
  1043.     )
  1044.     {
  1045.     return (ether_output ((IFNET*)pIDR, pMbuf, pDest, (FUNCPTR) exStart, pIDR));
  1046.     }
  1047. #endif
  1048. /*******************************************************************************
  1049. *
  1050. * exIoctl - process an ioctl request
  1051. */
  1052. LOCAL int exIoctl
  1053.     (
  1054.     IDR *pIDR,
  1055.     int cmd,
  1056.     caddr_t data
  1057.     )
  1058.     {
  1059.     int ret;
  1060.     ret = 0;
  1061.     switch (cmd)
  1062.         {
  1063.         case SIOCSIFADDR:
  1064.            ((struct arpcom *)pIDR)->ac_ipaddr = IA_SIN (data)->sin_addr;
  1065.             arpwhohas (pIDR, &IA_SIN (data)->sin_addr);
  1066.             break;
  1067.         case SIOCSIFFLAGS:
  1068.             /* Flags are set outside this module. No additional work to do. */
  1069.             break;
  1070.         default:
  1071.             ret = EINVAL;
  1072.         }
  1073.     return (ret);
  1074.     }
  1075. /*******************************************************************************
  1076. *
  1077. * exHostAdrs - get host address as required by EXOS board
  1078. *
  1079. * This routine converts the specified local address into the form
  1080. * that the EXOS board wants to see it, namely converted into
  1081. * the proper vme address space and, in the VME version, with the
  1082. * address modifier in the upper byte.
  1083. *
  1084. * RETURNS: proper EXOS access address or ERROR.
  1085. */
  1086. LOCAL char *exHostAdrs
  1087.     (
  1088.     char *localAdrs
  1089.     )
  1090.     {
  1091.     char *busAdrs;
  1092.     if (sysLocalToBusAdrs (exBusAdrsSpace, localAdrs, &busAdrs) != OK)
  1093.         {
  1094. #ifdef EX_DEBUG
  1095.         printErr ("ex: no bus access to local address 0x%x (AM=0x%x)n",
  1096.                   localAdrs, exBusAdrsSpace);
  1097. #endif
  1098.         return ((char*)ERROR);
  1099.         }
  1100.     if (sysBus == VME_BUS && !exBit32)
  1101.         {
  1102.         /* EXOS 202 (VME version) requires AM code in upper byte */
  1103.         busAdrs = (char *) ((int) busAdrs | (exBusAdrsSpace << 24));
  1104.         }
  1105.     return (busAdrs);
  1106.     }
  1107. /*******************************************************************************
  1108. *
  1109. * exGiveRequest - give request buffer to EXOS
  1110. */
  1111. LOCAL void exGiveRequest
  1112.     (
  1113.     EX_MSG      *pMsg,            /* pointer to msg buffer to give to EXOS */
  1114.     DEV_CTRL    *pDev             /* device address */
  1115.     )
  1116.     {
  1117.     pMsg->mb_status |= MH_EXOS;   /* give request to EXOS */
  1118.     if (sysBus == VME_BUS)
  1119.         pDev->bus.vme.xd_portb = EX_NTRUPT;
  1120.     else
  1121.         pDev->bus.multi.xd_portb = EX_NTRUPT;
  1122.     }
  1123. /* END OF FILE */