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

VxWorks

开发平台:

C/C++

  1. /* if_bp.c - original VxWorks (and SunOS) backplane network interface driver */
  2. /* Copyright 1984 - 1997 Wind River Systems, Inc. */
  3. #ifndef UNIX
  4. #include "copyright_wrs.h"
  5. #else   /* UNIX */
  6. static char *copyright=
  7.      "Copyright 1984 - 1997 Wind River Systems, Inc.";
  8. #endif  /* UNIX */
  9. /*
  10. modification history
  11. --------------------
  12. 01u,09oct97,spm  removed driver initialization from ioctl support (SPR #8831)
  13. 01t,07apr97,spm  code cleanup, corrected statistics, and upgraded to BSD 4.4
  14. 01s,25aug95,hk   use cacheDmaMalloc() for shared memory on SH7600 targets.
  15. 01r,12nov94,tmk  removed some IMPORTed function decs and included unixLib.h
  16. 01q,29mar94,caf  use cacheDmaMalloc() for shared memory on MIPS targets.
  17. 01p,23apr93,caf  ansification: changed cast of free() parameter.
  18. 01o,22feb93,jdi  documentation cleanup.
  19. 01n,18sep92,jcf  clean up of warnings.
  20. 01m,09sep92,gae  documentation tweaks.
  21. 01l,18jul92,smb  Changed errno.h to errnoLib.h.
  22. 01k,11jun92,elh  fixed memory sizing bug - SPR 1481.
  23. 01j,04jun92,ajm  added test and set suport for mips
  24. 01i,26may92,rrr  the tree shuffle
  25.   -changed includes to have absolute path from h/
  26. 01h,26may92,ajm  got rid of HOST_DEC def's (new compiler)
  27. 04g,05may92,wmd  changed LITTLE_ENDIAN to _LITTLE_ENDIAN, removed conditional
  28.  for i960 to pass IPL vec parameter in sysMailboxEnable().
  29. 04f,07apr92,yao  removed duplicated macro ROUND_UP.  removed unneccessary
  30.  ROUND_UP for SPARC.  changed copyright notice.
  31. 04e,14feb92,wmd  added BP_NTOHS, BP_HTONS for BUF_NODE->b_len conversions.
  32.  Fixed ansi warnings.
  33. 04d,27nov91,rfs  fixed bug in bpStart(), which did not handle errors
  34.                  correctly, causing memory depletion. Also fixed ANSI warnings.
  35. 04c,07oct91,rrr  turned off some checking in the r3000
  36. 04b,04oct91,rrr  passed through the ansification filter
  37.                   -changed functions to ansi style
  38.                   -changed functions to ansi style
  39.   -changed includes to have absolute path from h/
  40.   -fixed #else and #endif
  41.   -changed READ, WRITE and UPDATE to O_RDONLY O_WRONLY and O_RDWR
  42.   -changed VOID to void
  43.   -changed copyright notice
  44. 04a,01oct91,ajm  got rid of conditional comp (MIPS) for ItoKval, and KtoIval
  45. 03z,10sep91,wmd  added conditionals for MIPS.
  46. 03y,21aug91,ajm  added macros to allocate and free mips dynamic memory
  47.                  from uncached space
  48.                  cast line 1250 comparison with 0 to struct mbuf * to
  49.  resolve warning in mips land
  50. 03x,15aug91,rrr  added IPL to sysMailboxEnable() for I960_FAMILY
  51. 03w,23jul91,rrr  added hton and ntoh stuff so I960 would work
  52. 03v,12jul91,wmd  minor cleanup of 03u.  Added Al Maillet's fix to bpXmit
  53.  for the case that ringput returns > 1 available slots.
  54. 03u,24may91,hvh  deleted 'short-macros' because they screwed up
  55.    +jwt  and besides, they are not needed since a short on
  56.  the SPARC is 2 bytes (so no aligment problem);
  57.  deleted 'KLUDGES' for SPARC since they make no sence
  58.  and introduce gigantic interrupt-latencys in, what
  59.  is supposed to be, a realtime operating system;
  60.  included ELH 29dec91 bpPollTask check for NULL bp;
  61.  fixed TAS(x) macro for Sun-1E and others - bpTas().
  62. 03t,29apr91,hdn  use SIZEOF_ETHERHEADER instead of sizeof(ether_header).
  63. 03s,10apr91,jdi  documentation cleanup; doc review by dnw.
  64. 03r,29dec91,elh  changed bpPollTask to check if bp is null.
  65. 03q,10aug90,dnw  fixed forward declarations for void functions.
  66.  added include of if_subr.h.
  67. 03p,12aug90,hjb  added bpSlotCheck() to help BOOTP.
  68.  changed bp pseudo-Ethernet addr to be all 00.
  69. 03o,18jul90,hjb  deleted cluster-loan code temporarily; fixed a bug caused
  70.  by the macro ROUND_UP.
  71. 03n,15jul90,dnw  added b_pad to BUF_NODE structure to make it long aligned.
  72.  changed to round up BP_BUFSIZ to be long aligned.
  73.  removed B_COPY, B_ASSIGN, B_FROM macros
  74.  coerced malloc() to (char*) where necessary.
  75. 03m,11jul90,hjb  removed references to ipintr().
  76. 03l,26jun90,hjb  fixes to accommodate SunOS; copy_from_mbufs() & m_freem() fix;
  77.  changed params to build_cluster()
  78. 03k,19apr90,hjb  deleted param.h, added BP_SLOT_NUM, BP_MAX_LOANS,
  79.  DEBUG_OPTION_5, bpRIngFree(), modified bpRead()
  80.  to optimize throughput via cluster-callback-hack.
  81. 03j,18mar90,hjb  isolated out SunOS compatible routines for if_subr.c.
  82. 03i,07aug89,gae  adjusted BUF_NODE definition to work on SPARC; changed
  83.    iv68k.h to iv.h; fixed ether_attach to not append unit.
  84. 03h,14jun89,gae  glitch in 03g: left bpParity on and wrong poll task priority.
  85. 03g,14mar89,gae  used unsigned int's for pointer arithmetic.
  86.  made Ethernet address unique for multiple units.
  87.  slight reorganization of bpPollTask. Added more DEBUG levels.
  88. 03f,28mar89,gae  turned off debugging; fixed bp BUFSIZ to be bigger
  89.    than MTU to allow for ether_header overhead -- bug fix.
  90. 03e,10feb89,gae  taught SunOS to do mailboxes and about bus interrupts;
  91.    +jcf  added testing in bpInit for sufficient memory;
  92.            +dnw  added read mailboxes; fixed mbuf bug in copy_to_mbufs.
  93.  UNIX ver. now compiles under SunOS 4.0 and has SUN3_5 flag.
  94. 03c,10dec88,gae  SunOS version tweaks.
  95. 03b,20nov88,dnw  lint
  96. 03a,13sep88,gae  merged SunOS and VxWorks versions.  Documentation.
  97.    +dnw  debugged SunOS version.
  98.    +ak   wrote SunOS version.
  99. 02l,23jun88,rdc  added IFF_BROADCAST to if_flags.
  100. 02k,06jun88,dnw  changed taskSpawn/taskCreate args.
  101.  changed NCPU from 9 to 32.
  102. 02j,30may88,dnw  changed to v4 names.
  103. 02i,12apr88,gae  added include of ioLib.h for O_RDONLY/O_WRONLY/O_RDWR.
  104. 02h,28jan88,jcf  made kernel independent.
  105. 02g,20feb88,dnw  lint
  106. 02f,05jan88,rdc  added include of systm.h
  107. 02e,20nov87,ecs  lint
  108.     dnw  changed bpattach to take int vec num instead of vec adrs.
  109. 02d,13nov87,dnw  added heartbeat & anchor.
  110. 02c,03nov87,dnw  fixed bug in bpRead of throwing away packets that were
  111.    larger than 1500 bytes.
  112.  make bpPoll be global so that it is legible in i().
  113.  added intConnect() call for bus interrupt connects in
  114.    bpConnect().
  115.  changed bpReboot() into bpReset().
  116. 02b,26oct87,jcf  added bpConnect that does a sysMailboxConnect in the case of
  117.      &    mailbox interrupts or a spawn of bpPoll for non-interrupt
  118.     dnw   driven backplanes
  119.  changed to not probe shared memory unless cpu 0.
  120. 02a,22apr87,dnw  rewritten.
  121. 01b,08apr87,rdc  moved call to bpConnect from bpAttach to bpInit.
  122. 01x,01apr87,jlf  delinted, removed ifdef CLEAN.
  123.  changed calls to tas () to vxTas ().
  124.  added copyright.
  125. */
  126. /*
  127. DESCRIPTION
  128. This module implements the original VxWorks backplane network interface driver.
  129. The backplane driver allows several CPUs to communicate via shared
  130. memory.  Usually, the first CPU to boot in a card cage is considered the
  131. backplane master.  This CPU has either dual-ported memory or an additional
  132. memory board which all other CPUs can access.  Each CPU must be
  133. interruptible by another CPU, as well as be able to interrupt all other
  134. CPUs.  There are three interrupt types: polling, mailboxes, and VMEbus
  135. interrupts.  Polling is used when there are no hardware interrupts; each
  136. CPU spawns a polling task to manage transfers.  Mailbox interrupts are the
  137. preferred method, because they do not require an interrupt level.  VMEbus
  138. interrupts offer better performance than polling; however, they may
  139. require hardware jumpers.
  140. There are three user-callable routines: bpInit(), bpattach(), and bpShow().
  141. The backplane master, usually processor 0, must initialize the backplane
  142. memory and structures by first calling bpInit().  Once the backplane has
  143. been initialized, all processors can be attached via bpattach().  Usually,
  144. bpInit() and bpattach() are called automatically in usrConfig.c when
  145. backplane parameters have been specified in the boot line.
  146. The bpShow() routine is provided as a diagnostic aid
  147. to show all the CPUs configured on a backplane.
  148. For more information about SunOS use of this driver, see the 
  149. .I "Guide to the VxWorks Backplane Driver for SunOS."
  150. This driver has been replaced by if_sm and is included here for backwards
  151. compatibility.
  152. MEMORY LAYOUT
  153. All pointers in shared memory are relative to the start of shared memory,
  154. since dual-ported memory may appear in different places on different CPUs.
  155. .ne 11
  156. .CS
  157.    ---------------------------- low address (anchor)
  158.    |       ready value        |     1234567
  159.    |         heartbeat        |     increments 1/sec
  160.    |   pointer to bp header   |
  161.    |         watchdog         |     for backplane master CPU
  162.     --------------------------
  163.    the backplane header may be contiguous or
  164.    allocated elsewhere on the master CPU
  165. .ne 7 
  166.    ---------------------------- backplane header
  167.    |    backplane header      |     1234567
  168.    |       num CPUs           |     unused
  169.    |    Ethernet address      |     (6 bytes)
  170.    |   pointer to free ring   |
  171.    |--------------------------|
  172. .ne 11
  173.    |--------------------------| cpu descriptor
  174.    |        active            |     true/false
  175.    |   processor number       |     0-NCPU
  176.    |         unit             |     0-NBP
  177.    |   pointer to input ring  |
  178.    |    interrupt type        |     POLL  | MAILBOX    |  BUS
  179.    |    interrupt arg1        |     none  | addr space | level
  180.    |    interrupt arg2        |     none  | address    | vector
  181.    |    interrupt arg3        |     none  | value      | none
  182.    |--------------------------|
  183.               ...               repeated MAXCPU times
  184. .ne 16
  185.    |--------------------------|
  186.    |       free ring          |     contains pointers to buffer nodes
  187.    |--------------------------|
  188.    |       input ring 1       |     contains pointers to buffer nodes
  189.    |--------------------------|
  190.       ...
  191.    |--------------------------|
  192.    |       input ring n       |
  193.    |--------------------------|
  194.    |--------------------------| buffer node 1
  195.    |     address, length      |
  196.    |--------------------------|
  197.    |       data buffer 1      |
  198.    |--------------------------|
  199.       ...
  200. .ne 6
  201.    |--------------------------| buffer node m
  202.    |     address, length      |
  203.    |--------------------------|
  204.    |       data buffer m      |
  205.    ---------------------------- high address
  206. .CE
  207. BOARD LAYOUT
  208. This device is "software only."  A jumpering diagram is not applicable.
  209. INTERNAL
  210.  SOFTWARE ARCHITECTURE
  211. .CS
  212.     bpIoctl   |    bpOutput   bpPoll   bpattach  bpReset  bpInit
  213.       |    __/        |         |         /                |
  214.       |   /           |         |        /                 |
  215.       |  /            |         |       /                  |
  216.      bpIfinit    ether_output   |     bpAlive bpInit*    bpSizeMem
  217.       / |            |         |
  218.  bpAlive|bpIntEnable bpPut      |
  219.      bpConnect        |         | (interrupt level)
  220.        |            bpXmit      /    /
  221.        |                      /    /
  222.      bpPollTask              /    /
  223.      bpPollUnix             /    /
  224.                            /  __/
  225.                          bpintr
  226.                            |
  227.                         bpReadAll
  228.                            |
  229.                          bpRead
  230.  * UNIX only; called directly in VxWorks
  231. .CE
  232. SEE ALSO: ifLib
  233. */
  234. #ifdef UNIX
  235. #ifndef KERNEL
  236. #define KERNEL
  237. #endif /* KERNEL */
  238. #ifdef SUN3_5
  239. #include "h/types.h"
  240. #include "h/systm.h"
  241. #include "h/mbuf.h"
  242. #include "h/buf.h"
  243. #include "h/map.h"
  244. #include "h/socket.h"
  245. #include "h/vmmac.h"
  246. #include "h/errno.h"
  247. #else /* SUN3_5 */
  248. #include "sys/types.h"
  249. #include "sys/systm.h"
  250. #include "sys/mbuf.h"
  251. #include "sys/buf.h"
  252. #include "sys/map.h"
  253. #include "sys/socket.h"
  254. #include "sys/param.h"
  255. #include "sys/vmmac.h"
  256. #include "sys/errno.h"
  257. #endif /* SUN3_5 */
  258. #include "machine/param.h"
  259. #include "machine/pte.h"
  260. #ifdef SUN3_5
  261. #include "h/time.h"
  262. #include "h/kernel.h"
  263. #include "h/ioctl.h"
  264. #else /* SUN3_5 */
  265. #include "sys/time.h"
  266. #include "sys/kernel.h"
  267. #include "sys/ioctl.h"
  268. #endif /* SUN3_5 */
  269. #include "net/if.h"
  270. #include "netinet/in.h"
  271. #include "netinet/if_ether.h"
  272. #include "sundev/mbvar.h"
  273. #ifdef SUN3_5
  274. #include "h/protosw.h"
  275. #else /* SUN3_5 */
  276. #include "sys/protosw.h"
  277. #endif /* SUN3_5 */
  278. #include "net/route.h"
  279. #include "netinet/in_systm.h"
  280. #include "netinet/ip.h"
  281. #include "netinet/ip_var.h"
  282. #ifdef INET /* "vxWorks.h" defines INET */
  283. #undef INET
  284. #endif /* INET */
  285. #include "vxWorks.h"
  286. #include "vme.h" /* vxWorks vme AM's */
  287. #define BP_MASTER       (bp_procnum == 0)
  288. IMPORT int bp_tas;
  289. IMPORT int bp_procnum;
  290. IMPORT int bp_n;
  291. IMPORT int bp_mem_size;
  292. IMPORT char *bp_mem_adrs;
  293. IMPORT int bp_int_type;
  294. IMPORT int bp_int_arg1;
  295. IMPORT int bp_int_arg2;
  296. IMPORT int bp_int_arg3;
  297. IMPORT void wakeup ();
  298. IMPORT struct mbuf *copy_to_mbufs ();
  299. #else /* UNIX */
  300. #include "vxWorks.h"
  301. #include "iv.h"
  302. #include "taskLib.h"
  303. #include "memLib.h"
  304. #include "ioLib.h"
  305. #include "ioctl.h"
  306. #include "etherLib.h"
  307. #include "wdLib.h"
  308. #include "iosLib.h"
  309. #include "intLib.h"
  310. #include "logLib.h"
  311. #include "netLib.h"
  312. #include "net/mbuf.h"
  313. #include "socket.h"
  314. #include "net/protosw.h"
  315. #include "errnoLib.h"
  316. #include "net/systm.h"
  317. #include "net/route.h"
  318. #include "netinet/in.h"
  319. #include "netinet/in_systm.h"
  320. #include "netinet/ip.h"
  321. #include "netinet/ip_var.h"
  322. #include "net/if.h"
  323. #include "net/unixLib.h"
  324. #include "netinet/if_ether.h"
  325. #include "net/if_subr.h"
  326. #include "netinet/in_var.h"
  327. #include "vxLib.h"
  328. #include "stdio.h"
  329. #include "stdlib.h"
  330. #include "sysLib.h"
  331. #if ((CPU_FAMILY==MIPS) || (CPU_FAMILY==SH))
  332. #include "cacheLib.h"
  333. #endif /* CPU_FAMILY==MIPS || CPU_FAMILY==SH */
  334. #endif /* UNIX */
  335. #include "drv/netif/if_ring.h"
  336. #include "if_bp.h"
  337. IMPORT struct ifnet *ifunit ();
  338. #if defined (BSD43_DRIVER) || defined (UNIX)
  339. IMPORT int    ether_output (struct ifnet *ifp, struct mbuf *m0,
  340.      struct sockaddr *dst, FUNCPTR startRtn,
  341.      struct arpcom *pArpcom);
  342. #endif
  343. IMPORT int    set_if_addr (struct ifnet *ifp,char *data,u_char *enaddr);
  344. IMPORT void   m_freem (struct mbuf *m);
  345. #define MAXCPU 32 /* don't change! */
  346. #define NCPU 32 /* number of input rings to init */
  347. #define MINPKTSIZE 60 /* minimum packet size to send */
  348. #define BP_SLOT_NUM 32 /* number of the input ring slots */
  349. #define BP_MTU ((2 * 1024) + 128)
  350. int bp_mtu = BP_MTU; /* patch before calling bpInit */
  351. /* round up bufsiz to be long aligned */
  352. #define BP_BUFSIZ       (ROUND_UP (bp_mtu + SIZEOF_ETHERHEADER, 4))
  353. #ifdef UNIX
  354. #define logMsg          printf
  355. #define WDOG_ID int
  356. #define vir2phys(v) (unsigned)ptob((unsigned)hat_getkpfnum(v))
  357. #define splimp() spl3()
  358. #define NBP 1 /* max # bp interfaces */
  359. #else /* UNIX */
  360. #define hz (sysClkRateGet ())
  361. #define NBP 2 /* max. # bp interfaces */
  362. #define vir2phys(v) (v)
  363. #endif /* UNIX */
  364. typedef struct ring RING;
  365. typedef struct /* buffer node */
  366.     {
  367.     char *b_addr; /* buffer address (as offset) */
  368.     short       b_len; /* buffer length */
  369.     short b_pad; /* padding to make structure long aligned */
  370.     } BUF_NODE;
  371. typedef struct /* CPU descriptor in bp header */
  372.     {
  373.     BOOL cd_active; /* CPU is present */
  374.     int cd_cpuNum; /* processor number */
  375.     int cd_unit; /* unit on own CPU */
  376.     RING *cd_pInputRing;
  377.     int cd_intType; /* interrupt: poll, bus, or mailbox */
  378.     int cd_intArg1;
  379.     int cd_intArg2;
  380.     int cd_intArg3;
  381.     } CPU_DESC;
  382. typedef struct /* bp header */
  383.     {
  384.     int hdr_ready; /* used only as marker for debugging */
  385.     short hdr_ncpu; /* unused */
  386.     u_char hdr_enetAdrs[6];/* "Ethernet address" */
  387.     RING *hdr_pFreeRing;
  388.     CPU_DESC hdr_cpuDesc[MAXCPU];
  389.     } BP_HEADER;
  390. typedef struct /* bp anchor */
  391.     {
  392.     int an_ready; /* special value 1234.... */
  393.     UINT an_heartbeat; /* increments every second */
  394.     BP_HEADER *an_pHdr; /* separate to minimize usage of low memory */
  395.     WDOG_ID an_wdog; /* for VxWorks version only */
  396.     } BP_ANCHOR;
  397. #define BP_READY   0x12345678 /* distinctive ready value */
  398. #define BP_READY_SOFT_TAS 0x12344321 /* ready value with software tas */
  399. #if _BYTE_ORDER==_LITTLE_ENDIAN
  400. #define BP_NTOHL(v) ntohl(v)
  401. #define BP_NTOHS(v) ntohs(v)
  402. #define BP_HTONL(v) htonl(v)
  403. #define BP_HTONS(v) htons(v)
  404. #else
  405. #define BP_NTOHL(v) (v)
  406. #define BP_NTOHS(v) (v)
  407. #define BP_HTONL(v) (v)
  408. #define BP_HTONS(v) (v)
  409. #endif  /* _BYTE_ORDER==_LITTLE_ENDIAN */
  410. #define ItoKval(p,type,base) ((type)(ntohl((u_int)(p)) + (u_int)(base)))
  411. #define KtoIval(p,type,base) ((type)htonl((u_int)(p) - (u_int)(base)))
  412. /*
  413.  * Net software status per interface.
  414.  *
  415.  * Each interface is referenced by a network interface structure,
  416.  * bs_if, which the routing code uses to locate the interface.
  417.  * This structure contains the output queue for the interface, its address, ...
  418.  */
  419. typedef struct
  420.     {
  421.     struct arpcom bs_ac; /* common Ethernet structures */
  422. #define bs_if           bs_ac.ac_if     /* network-visible interface */
  423. #define bs_enaddr       bs_ac.ac_enaddr /* hardware Ethernet address */
  424.     int bs_procNum; /* processor number on this net */
  425.     BP_ANCHOR *bs_pAnchor; /* pointer to bp anchor */
  426.     BP_HEADER *bs_pHdr; /* pointer to bp header */
  427.     volatile RING       *bs_pFreeRing;  /* pointer to free ring */
  428.     volatile RING       *bs_pInputRing; /* pointer to our input ring */
  429.     volatile BOOL       bs_readPending; /* read interrupt is outstanding */
  430.     int bs_intType; /* interrupt type: poll, bus, mailbox */
  431.     int bs_intArg1;
  432.     int bs_intArg2;
  433.     int bs_intArg3;
  434. #ifdef UNIX
  435.     caddr_t  bs_addr;
  436.     u_char  bs_ivec;
  437. #endif /* UNIX */
  438.     } BP_SOFTC;
  439. #ifdef UNIX
  440. extern struct mb_driver bpdriver;
  441. struct mb_device *bpinfo[NBP];
  442. LOCAL BP_SOFTC bp_softc [NBP];
  443. #define BP_SOFTC_P &bp_softc
  444. #define dbgprintf printf
  445. #define sysProcNumGet() (bp_procnum)
  446. FUNCPTR bpProbeType;
  447. LOCAL char *cpudesc_vaddr [MAXCPU];
  448. #else /* UNIX */
  449. /* bpPollTask parameters */
  450. int bpPollTaskId;
  451. int bpPollTaskOptions = VX_SUPERVISOR_MODE | VX_UNBREAKABLE;
  452. int bpPollTaskStackSize = 2000;
  453. int bpPollTaskPriority = 250;
  454. LOCAL BP_SOFTC *bp_softc[NBP];
  455. #define BP_SOFTC_P bp_softc
  456. #define dbgprintf logMsg
  457. int bpProbeType;
  458. #endif /* UNIX */
  459. LOCAL  BOOL vxTasac ();
  460. /*
  461.  * the default TAS, use undef if you dont like it
  462.  */
  463. #define TAS(x)  (bpTasOK ? sysBusTas (x) : vxTasac (x))
  464. #if     (CPU_FAMILY==MIPS)
  465. #define TAS_CLEAR(x)    (bpTasOK ? sysBusClearTas (&(x)) : ((x)=0))
  466. #endif  /* CPU_FAMILY==MIPS */
  467. #if  CPU_FAMILY==SPARC
  468. IMPORT BOOL vxTas ();
  469. IMPORT BOOL sysBusTas ();
  470. FUNCPTR         bpTasRtn = vxTasac;  /* Test-and-Set Routine */
  471. #undef TAS(x)
  472. #define TAS(x)  (*bpTasRtn)(x)
  473. /*******************************************************************************
  474. *
  475. * bpTas - determine backplane test-and-set macro TAS(x)
  476. *
  477. * NOMANUAL
  478. */
  479. void bpTas (bp_tas, bp_off_board, bp_target)
  480.     BOOL bp_tas; /* BP_TAS */
  481.     BOOL bp_off_board; /* BP_OFF_BOARD */
  482.     int  bp_target; /* target id */
  483.     {
  484.     if (!bp_tas)
  485.       bpTasRtn = vxTasac;       /* software TAS */
  486.     else
  487. {
  488. /* hardware TAS */
  489. if (bp_target == 0x1E)
  490.     {
  491.     /* Sun-1E */
  492.     if (bp_off_board)
  493. bpTasRtn = vxTas;
  494.     else
  495. bpTasRtn = sysBusTas;
  496.     }
  497. else
  498.     {
  499.     if (bp_off_board)
  500. bpTasRtn = sysBusTas;
  501.     else
  502. bpTasRtn = vxTas;
  503.     }
  504. }
  505.     }
  506. #endif /* CPU_FAMILY==SPARC */
  507. #ifdef UNIX
  508. #define intLock spl7
  509. #define intUnlock splx
  510. #endif /* UNIX */
  511. #define DELAY_COUNT 5000 /* how high to count when waiting on TAS */
  512. #ifdef UNIX
  513. IMPORT int bpParity;
  514. IMPORT int bpDebug; /* flags: 1-usage, 2-dropped packets */
  515. #else /* UNIX */
  516. int bpParity = FALSE;
  517. int bpDebug; /* flags: 1-usage, 2-dropped packets */
  518. #endif /* UNIX */
  519. #define DEBUG_OPTION_1 (bpDebug & 0x1)
  520. #define DEBUG_OPTION_2 (bpDebug & 0x2)
  521. #define DEBUG_OPTION_3 (bpDebug & 0x4)
  522. #define DEBUG_OPTION_4 (bpDebug & 0x8)
  523. #define DEBUG_OPTION_5 (bpDebug & 0x10)
  524. /*  0, 0, 0, 0, unit, host */
  525. u_char bpEnetAdrs [6] = { 0, 0, 0, 0, 0, 0 };
  526. /* local variables */
  527. LOCAL BOOL bpTasOK; /* whether hardward can do test-and-set */
  528. LOCAL int bpHeartbeatRate;
  529. int bpBitBucket; /* spare change */
  530. /* forward declarations */
  531. void bpPollTask ();
  532. void bpintr ();
  533. /* forward static functions */
  534. static void bpReset (int unit);
  535. static STATUS bpAlive (BP_SOFTC *bs);
  536. static STATUS bpIfInit (int unit);
  537. static void bpReadAll (int unit);
  538. static STATUS bpRead (BP_SOFTC *bs, BUF_NODE *pBufNode, BUF_NODE
  539. *pBufNodeOrig);
  540. #if defined BSD43_DRIVER || defined (UNIX)
  541. static void bpStart (int unit);
  542. static int bpOutput (struct ifnet *ifp, struct mbuf *m0, struct sockaddr
  543. *dst);
  544. #else
  545. static void bpStart (BP_SOFTC *  bs);
  546. #endif
  547. static STATUS bpPut (BP_SOFTC *bs, struct mbuf *m);
  548. static void bpXmit (BP_SOFTC *bs, BUF_NODE *pBufNode, int destProcNum, int
  549. srcProcNum);
  550. static void bpIntAck (BP_SOFTC *bs);
  551. static STATUS bpConnect (BP_SOFTC *bs, int unit);
  552. static STATUS bpIntEnable (BP_SOFTC *bs);
  553. static void bpIntGen (CPU_DESC *pCpu, int srcProcNum);
  554. static void bpHeartbeat (BP_ANCHOR *pAnchor);
  555. static int bpSizeMem (caddr_t memAdrs, int memSize);
  556. static int bpIoctl (struct ifnet *ifp, int cmd, caddr_t data);
  557. static void ringinit (RING *rp, short size);
  558. #if CPU==R3000
  559. static int ringput ();
  560. static int ringget ();
  561. #else
  562. static int ringput (RING *rp, int v);
  563. static int ringget (RING *rp);
  564. #endif
  565. static int ringcount (RING *pRing);
  566. static BOOL vxTasac (char *address);
  567. #ifdef UNIX
  568. LOCAL void bpRead ();
  569. #else /* UNIX */
  570. LOCAL STATUS bpRead ();
  571. #endif /* UNIX */
  572. #ifdef UNIX
  573. /*******************************************************************************
  574. *
  575. * bpattach - attach the `bp' interface to the network
  576. *
  577. * Make the `bp' interface available by filling in the network interface record.
  578. * The system will initialize the interface when it is ready to accept packets.
  579. *
  580. * RETURNS: N/A
  581. *
  582. * NOMANUAL
  583. */
  584. void bpattach (md)
  585.     struct mb_device *md;
  586.     {
  587.     int unit          = md->md_unit;
  588.     FAST BP_SOFTC *bs = BP_SOFTC_P [unit];
  589.     struct ifnet *ifp = &bs->bs_if;
  590.     bs->bs_procNum = bp_procnum;
  591.     bs->bs_intType = bp_int_type;
  592.     bs->bs_intArg1 = bp_int_arg1;
  593.     bs->bs_intArg2 = bp_int_arg2;
  594.     bs->bs_intArg3 = bp_int_arg3;
  595.     bs->bs_addr = md->md_addr;
  596.     bs->bs_ivec = md->md_intr->v_vec;
  597.     ether_attach (ifp, unit, "bp", bpIfInit, bpIoctl, bpOutput,
  598.                   (FUNCPTR)bpReset);
  599.     ifp->if_mtu = bp_mtu;
  600.     bzero ((char*) cpudesc_vaddr, sizeof (cpudesc_vaddr));
  601.     }
  602. /*******************************************************************************
  603. *
  604. * bpPoke - map in physical memory and write value to address
  605. *
  606. * This routine is used to map in CPU boards' mailboxes.
  607. * An array up to MAXCPU is kept so that a mailbox is
  608. * only mapped in once per CPU.
  609. */
  610. LOCAL void bpPoke (addr, type, value, cpuNum)
  611.     char *addr; /* physical address */
  612.     int type; /* mailbox size + read/write */
  613.     int value; /* value to write */
  614.     int cpuNum; /* which CPU */
  615.     {
  616.     char *vaddr; /* virtual address */
  617.     int kmx; /* kernel map index */
  618.     int numClicks;
  619.     /* int numBytes; */
  620.     int addrOffset;
  621.     if (cpuNum < 0 && cpuNum > MAXCPU)
  622. {
  623. printf ("bp: bpPoke invalid cpu #%dn", cpuNum);
  624. return;
  625. }
  626.     if ((vaddr = cpudesc_vaddr [cpuNum]) == 0)
  627. {
  628. numClicks = btoc (sizeof (int));
  629. /* numBytes = ctob (numClicks); */
  630. addrOffset = (int)(addr - ptob (btop (addr)));
  631. /* get some virtual address space */
  632. if ((kmx = rmalloc (kernelmap, numClicks)) == 0)
  633.     {
  634.     printf ("bp: no kernelmap for bp mailboxn");
  635.     panic ("bpPoke");
  636.     }
  637. vaddr = (char *)kmxtob (kmx);
  638. mapin (&Usrptmap [kmx], btop (vaddr), btop (addr) | PGT_VME_D16,
  639. numClicks, PG_V | PG_KW);
  640. cpudesc_vaddr [cpuNum] = vaddr += addrOffset;
  641. if (DEBUG_OPTION_1)
  642.     printf ("nbp: cpu #%d mailbox addr = 0x%x, vaddr = 0x%xn",
  643.     cpuNum, (int)addr, (int)vaddr);
  644. }
  645.     switch (type)
  646. {
  647. case BP_INT_MAILBOX_1: *(char  *) vaddr = value; break;
  648. case BP_INT_MAILBOX_2: *(short *) vaddr = value; break;
  649. case BP_INT_MAILBOX_4: *(long  *) vaddr = value; break;
  650. case BP_INT_MAILBOX_R1: value = *(char  *) vaddr; break;
  651. case BP_INT_MAILBOX_R2: value = *(short *) vaddr; break;
  652. case BP_INT_MAILBOX_R4: value = *(long  *) vaddr; break;
  653. default: printf ("bp: bpPoke - bad mailbox type 0x%xn", type); break;
  654. }
  655. #ifdef MAP_OUT
  656.     /* example of mapping out memory */
  657.     cpudesc_vaddr [cpuNum] = 0;
  658.     mapout (&Usrptmap [kmx], numClicks, kmx);
  659.     rmfree (kernelmap, numClicks, kmx);
  660. #endif /* MAP_OUT */
  661.     }
  662. /*******************************************************************************
  663. *
  664. * bpProbe - probe for backplane memory
  665. *
  666. * RETURNS:
  667. * The amount of memory available, or 0 if error.
  668. *
  669. * NOMANUAL
  670. */
  671. int bpProbe (addr, unit)
  672.     caddr_t addr; /* address of backplane memory */
  673.     int unit; /* device number */
  674.     {
  675.     int memSize = bp_mem_size;
  676.     FAST BP_SOFTC *bs = BP_SOFTC_P [unit];
  677.     extern int peek (), pokec ();
  678.     if (BP_MASTER)
  679. bpProbeType = bpParity ? pokec : peek;
  680.     else
  681. bpProbeType = peek;
  682.     if (DEBUG_OPTION_1)
  683. printf ("bp%d: debugging on (level = 0x%x)n", unit, bpDebug);
  684.     /* anchor is at the start of shared memory */
  685.     bs->bs_pAnchor = (BP_ANCHOR *) addr;
  686.     if ((*bpProbeType) (addr, 0) == -1)
  687. {
  688. printf ("bp%d: shared memory not present at 0x%x (0x%x)n",
  689. unit, (int)bs->bs_pAnchor,(int)vir2phys((char*)bs->bs_pAnchor));
  690. return (0);
  691. }
  692.     if (BP_MASTER &&
  693. bpInit ((char*)bs->bs_pAnchor, addr, memSize, bp_tas) == ERROR)
  694. {
  695. printf ("bp%d: bpProbe cannot initialize anchor!n", unit);
  696. return (0);
  697. }
  698.     if (DEBUG_OPTION_1)
  699. printf ("bp%d: shared memory size is %d bytes, at 0x%x (0x%x)n", unit,
  700.      memSize,(int)bs->bs_pAnchor, (int)vir2phys((char*)bs->bs_pAnchor));
  701.     return (memSize);
  702.     }
  703. #else /* UNIX */
  704. /*******************************************************************************
  705. *
  706. * bpattach - publish the `bp' network interface and initialize the driver and device
  707. *
  708. * This routine attaches a `bp' interface to the network, if the
  709. * interface exists.  This routine makes the interface available by filling in
  710. * the network interface record.  The system will initialize the interface
  711. * when it is ready to accept packets.
  712. *
  713. * RETURN: OK or ERROR.
  714. */
  715. STATUS bpattach
  716.     (
  717.     int unit,           /* backplane unit number */
  718.     char *pAnchor,      /* bus pointer to bp anchor */
  719.     int procNum,        /* processor number in backplane */
  720.     int intType,        /* interrupt type: poll, bus, mailbox */
  721.     int intArg1,        /* as per interrupt type */
  722.     int intArg2,        /* as per interrupt type */
  723.     int intArg3         /* as per interrupt type */
  724.     )
  725.     {
  726.     FAST BP_SOFTC *bs;
  727.     FAST struct ifnet *ifp;
  728.     FAST BP_ANCHOR *pBpAnchor = (BP_ANCHOR *) pAnchor;
  729.     if (procNum == 0)
  730. bpProbeType = bpParity ? O_WRONLY : O_RDONLY;
  731.     else
  732. bpProbeType = O_RDONLY;
  733.     /* allocate bp_softc structure */
  734.     if ((bs = (BP_SOFTC *) malloc (sizeof (BP_SOFTC))) == NULL)
  735. return (ERROR);
  736.     bp_softc [unit] = bs; /* XXX check if non-zero for re-attach? */
  737.     ifp = &bs->bs_if;
  738.     /* initialize the interface structure */
  739.     bzero ((char *) bs, sizeof (BP_SOFTC));
  740.     bs->bs_pAnchor = pBpAnchor;
  741.     bs->bs_procNum = procNum;
  742.     bs->bs_intType = intType;
  743.     bs->bs_intArg1 = intArg1;
  744.     bs->bs_intArg2 = intArg2;
  745.     bs->bs_intArg3 = intArg3;
  746.     /* wait for shared memory to be initialized; master CPU does sanity check */
  747.     if (bpAlive (bs) == ERROR)
  748. {
  749. (void) free ((void *) bs);
  750. return (ERROR);
  751. }
  752.     if (bpDebug != 0)
  753. {
  754. printf ("bp%d: debugging on (level = 0x%x)n", unit, bpDebug);
  755. printf ("bpattach: anchor CPU can%s do real TAS.n",
  756. bpTasOK ? "" : "not");
  757. }
  758. #ifdef BSD43_DRIVER
  759.     ether_attach (ifp, unit, "bp", bpIfInit, bpIoctl, bpOutput,
  760.                   (FUNCPTR)bpReset);
  761. #else
  762.     ether_attach (
  763.                  ifp,
  764.                  unit,
  765.                  "bp",
  766.                  (FUNCPTR) bpIfInit,
  767.                  (FUNCPTR) bpIoctl,
  768.                  (FUNCPTR) ether_output,
  769.                  (FUNCPTR) bpReset
  770.                  );
  771.     ifp->if_start = (FUNCPTR)bpStart;
  772. #endif
  773.     ifp->if_mtu = bp_mtu;
  774.     if (bpIfInit (unit) == ERROR)
  775.         {
  776.         (void) free ((void *) bs);
  777.         return (ERROR);
  778.         }
  779.     return (OK);
  780.     }
  781. #endif /* UNIX */
  782. /*******************************************************************************
  783. *
  784. * bpInit - initialize the backplane anchor
  785. *
  786. * This routine initializes the backplane anchor.  Typically, <pAnchor> and
  787. * <pMem> both point to the same block of shared memory.  If the first
  788. * processor is dual-porting its memory, then, by convention, the anchor is
  789. * at 0x600 (only 16 bytes are required) and the start of memory <pMem> is
  790. * dynamically allocated by using the value NONE (-1).  <memSize> should be at
  791. * least 64 Kbytes.  The <tasOK> parameter is provided for CPUs that do
  792. * not support the test-and-set instruction.  If the system includes any
  793. * test-and-set deficient CPUs, then all CPUs must use the software
  794. * "test-and-set".
  795. *
  796. * RETURNS:
  797. * OK, or ERROR if data structures cannot be set up or memory is insufficient.
  798. */
  799. STATUS bpInit
  800.     (
  801.     FAST char *pAnchor, /* backplane anchor address */
  802.     FAST char *pMem,    /* start of backplane shared memory, NONE = alloc */
  803.     int memSize,        /* no. bytes in bp shared memory, 0 = 0x100000 */
  804.     BOOL tasOK          /* TRUE = hardware can do test-and-set */
  805.     )
  806.     {
  807.     FAST BP_ANCHOR *pBpAnchor = (BP_ANCHOR *) pAnchor;
  808.     FAST RING *pFreeRing;
  809.     FAST int ix;
  810.     FAST char *pMemEnd; /* end of backplane shared memory */
  811.     FAST CPU_DESC *pCpu;
  812.     FAST BP_HEADER *pHdr;
  813.     int npackets = 0;
  814.     memSize = (memSize == 0) ? 0x100000 : memSize;
  815.     bpTasOK = tasOK;
  816.     /* if bp header specified, probe it, otherwise malloc it */
  817.     if (pMem != (char *) NONE)
  818. {
  819. memSize = min (memSize, bpSizeMem (pMem, memSize));
  820. if (memSize == 0)
  821.     {
  822.     printf ("bp: no shared memory at address 0x%xn", (int)pMem);
  823.     return (ERROR);
  824.     }
  825. /* if anchor is at start of shared region, skip over it */
  826. if (pMem == pAnchor)
  827.     {
  828.     pMem    += sizeof (BP_ANCHOR);
  829.     memSize -= sizeof (BP_ANCHOR);
  830.     }
  831. }
  832.     else
  833. {
  834. #ifndef UNIX
  835. #if ((CPU_FAMILY==MIPS) || (CPU_FAMILY==SH))
  836. if ((pMem = (char *) cacheDmaMalloc ((unsigned) memSize)) == NULL)
  837. #else /* CPU_FAMILY==MIPS || CPU_FAMILY==SH */
  838.         if ((pMem = (char *) malloc ((unsigned) memSize)) == NULL)
  839. #endif /* CPU_FAMILY==MIPS || CPU_FAMILY==SH */
  840. #endif /* UNIX */
  841.     {
  842.     printf ("bp: can't allocate shared memoryn");
  843.     return (ERROR);
  844.     }
  845. }
  846.     pMemEnd = pMem + memSize;
  847.     pHdr = (BP_HEADER *) pMem;
  848.     /* initialize bp anchor region */
  849.     pBpAnchor->an_ready     = 0; /* set bp not ready */
  850.     pBpAnchor->an_heartbeat = 0; /* clear heartbeat */
  851.     pBpAnchor->an_pHdr      = KtoIval (pHdr, BP_HEADER *, pAnchor);
  852.     if (pMem + sizeof (BP_HEADER) > pMemEnd)
  853. {
  854. printf ("bp: bpInit out of memory!n");
  855. return (ERROR);
  856. }
  857.     /* initialize bp header region */
  858.     pHdr->hdr_ready = 0;                /* set CPU region not ready */
  859.     pHdr->hdr_ncpu = BP_HTONS(NCPU);    /* set number of CPUs */
  860.     bcopy ((char *) bpEnetAdrs, (char *) pHdr->hdr_enetAdrs, 6);
  861.     /* initialize each CPU descriptor */
  862.     for (ix = 0; ix < MAXCPU; ++ix)
  863. {
  864. pCpu = &pHdr->hdr_cpuDesc[ix];
  865. pCpu->cd_active      = FALSE;
  866. pCpu->cd_cpuNum      = BP_HTONL(ix);
  867. pCpu->cd_pInputRing  = NULL;
  868. }
  869.     /* initialize free ring */
  870.     pMem += sizeof (BP_HEADER);
  871.     if ((pMem + sizeof (struct ring256) + NCPU * sizeof (struct ring32))
  872. > pMemEnd)
  873. {
  874. printf ("bp: bpInit out of memory!n");
  875. return (ERROR);
  876. }
  877.     ringinit ((pFreeRing = (RING *) pMem), 256);
  878.     pHdr->hdr_pFreeRing =  KtoIval (pFreeRing, RING *, pAnchor);
  879.     pMem += sizeof (struct ring256);
  880.     /* initialize each input ring */
  881.     for (ix = 0; ix < NCPU; ++ix)
  882. {
  883. ringinit ((RING *) pMem, 32);
  884. pHdr->hdr_cpuDesc[ix].cd_pInputRing = KtoIval (pMem, RING *, pAnchor);
  885. pMem += sizeof (struct ring32);
  886. }
  887.     /* initialize as many buffer blocks as will fit in remaining shared memory*/
  888.     if ((pMem + sizeof (BUF_NODE) + BP_BUFSIZ) > pMemEnd)
  889. {
  890. printf ("bp: bpInit out of memory!n");
  891. return (ERROR);
  892. }
  893.     while ((pMem + sizeof (BUF_NODE) + BP_BUFSIZ) <= pMemEnd)
  894. {
  895. ((BUF_NODE *)pMem)->b_addr = KtoIval (pMem + sizeof (BUF_NODE),
  896.       char*, pAnchor);
  897.         ((BUF_NODE *)pMem)->b_len = BP_BUFSIZ;
  898. (void) ringput (pFreeRing, KtoIval (pMem, int, pAnchor));
  899. pMem += sizeof (BUF_NODE) + BP_BUFSIZ;
  900. npackets++;
  901. }
  902.     if (DEBUG_OPTION_1)
  903. {
  904. printf ("bp: number of %d byte packets is %dn", BP_BUFSIZ, npackets);
  905. printf ("bp: %d bytes unused from 0x%x to 0x%xn",
  906. (int) (pMemEnd - pMem), 
  907. (int) vir2phys (pMem), 
  908. (int) vir2phys (pMemEnd));
  909. }
  910.     /* mark bp as ready */
  911.     if (bpTasOK)
  912. pHdr->hdr_ready = pBpAnchor->an_ready = BP_HTONL(BP_READY);
  913.     else
  914. pHdr->hdr_ready = pBpAnchor->an_ready = BP_HTONL(BP_READY_SOFT_TAS);
  915.     /* start heartbeat */
  916.     bpHeartbeatRate = hz;
  917. #ifdef UNIX
  918.     timeout (bpHeartbeat, (caddr_t) pAnchor, bpHeartbeatRate);
  919. #else /* UNIX */
  920.     /* create watchdog timer for heartbeat */
  921.     if ((pBpAnchor->an_wdog = wdCreate ()) == NULL)
  922. return (ERROR);
  923.     wdStart (pBpAnchor->an_wdog, bpHeartbeatRate, (FUNCPTR) bpHeartbeat,
  924.              (int) pAnchor);
  925. #endif /* UNIX */
  926.     return (OK);
  927.     }
  928. /*******************************************************************************
  929. *
  930. * bpReset - mark a bp inactive
  931. *
  932. * called from reboot and panic
  933. */
  934. LOCAL void bpReset
  935.     (
  936.     FAST int unit
  937.     )
  938.     {
  939.     FAST BP_SOFTC *bs;
  940.     FAST BUF_NODE *pBufNode;
  941. #ifdef UNIX
  942.     FAST struct mb_device *md;
  943.     if (unit >= NBP || (md = bpinfo[unit]) == 0 || md->md_alive == 0)
  944. return;
  945. #endif /* UNIX */
  946.     bs = BP_SOFTC_P [unit];
  947.     if (bs != NULL && bs->bs_pHdr != NULL)
  948. {
  949. /* turn off active flag in our CPU descriptor in the
  950.  * shared header, then throw away anything on our input ring */
  951. bs->bs_pHdr->hdr_cpuDesc[bs->bs_procNum].cd_active = FALSE;
  952. while ( (pBufNode = (BUF_NODE *)ringget ( (RING *)bs->bs_pInputRing)))
  953.     (void)ringput ( (RING *)bs->bs_pFreeRing, (int)pBufNode);
  954. }
  955.     }
  956. /*******************************************************************************
  957. *
  958. * bpAlive - check for throbbing heartbeat
  959. *
  960. * This routine is called for CPU 0 (master) as well as the rest.
  961. * The timeout is quick if the master can't see its own ticker.
  962. *
  963. * RETURNS: OK or ERROR if unable to find anchor after 10 minutes
  964. */
  965. LOCAL STATUS bpAlive
  966.     (
  967.     BP_SOFTC *bs
  968.     )
  969.     {
  970.     int readyValue;
  971.     int heartbeat;
  972.     FAST unsigned int oldBeat = 0;
  973.     FAST int countdown             = 10 * 60 * hz; /* wait 10 minutes */
  974.     FAST BP_ANCHOR *pAnchor        = bs->bs_pAnchor;
  975. #ifdef UNIX
  976.     int level = spl3 (); /* find out priority level */
  977.     splx (level);
  978. #endif /* UNIX */
  979.     if (bs->bs_procNum == 0)
  980. countdown = 2 * hz; /* don't wait around for self if master CPU */
  981.     while (--countdown > 0)
  982. {
  983. /* probe test:
  984.  *  1) anchor must be readable (memory must be visable to us),
  985.  *  2) anchor ready value must be BP_READY or BP_READY_SOFT_TAS,
  986.  *  3) anchor heartbeat must be increasing.
  987.  */
  988. #ifdef UNIX
  989. if (peek ((short *) &pAnchor->an_ready)     != -1 &&
  990.     peek ((short *) &pAnchor->an_heartbeat) != -1)
  991.     {
  992.     readyValue = BP_NTOHL(pAnchor->an_ready);
  993.     heartbeat  = (UINT)BP_NTOHL(pAnchor->an_heartbeat);
  994. #else /* UNIX */
  995. if (vxMemProbe ((char *) &pAnchor->an_ready,
  996.  O_RDONLY, 4, (char *) &readyValue) == OK &&
  997.     vxMemProbe ((char *) &pAnchor->an_heartbeat,
  998.  O_RDONLY, 4, (char *) &heartbeat) == OK)
  999.     {
  1000.     readyValue = BP_NTOHL(readyValue);
  1001.     heartbeat = (UINT)BP_NTOHL(heartbeat);
  1002. #endif /* UNIX */
  1003.     if ((countdown % 10) == 6)
  1004. {
  1005. printf ("nbp: bpAlive ready = 0x%x, heartbeat = %dn",
  1006.     readyValue, heartbeat);
  1007. }
  1008.     if (readyValue == BP_READY || readyValue == BP_READY_SOFT_TAS)
  1009. {
  1010. if (oldBeat == 0 || heartbeat <= oldBeat)
  1011.     oldBeat = heartbeat;
  1012. else
  1013.     {
  1014.     /* heartbeat increased, passed test */
  1015.     bpTasOK = readyValue == BP_READY;
  1016.     return (OK);
  1017.     }
  1018. }
  1019.     }
  1020. else if ((countdown % 10) == 8)
  1021.     printf ("nbp: bpAlive bus errorn");
  1022. #ifdef UNIX
  1023. timeout (wakeup, (caddr_t)bs, 1);
  1024.         sleep (bs, level);
  1025. #else /* UNIX */
  1026. taskDelay (hz);
  1027. #endif /* UNIX */
  1028. }
  1029. #ifndef UNIX
  1030.     (void) errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT);
  1031. #endif /* UNIX */
  1032.     /* give up - didn't get initialized */
  1033.     return (ERROR);
  1034.     }
  1035. /*******************************************************************************
  1036. *
  1037. * bpIfInit - initialize interface
  1038. *
  1039. * RETURNS: OK or ERROR
  1040. */
  1041. LOCAL STATUS bpIfInit
  1042.     (
  1043.     int unit
  1044.     )
  1045.     {
  1046.     FAST CPU_DESC *pCpu;
  1047.     FAST BP_SOFTC *bs = BP_SOFTC_P [unit];
  1048.     FAST BP_HEADER *pHdr;
  1049.     /* find the anchor and CPU descriptor */
  1050.     pHdr = ItoKval (bs->bs_pAnchor->an_pHdr, BP_HEADER *, bs->bs_pAnchor);
  1051.     bs->bs_pHdr = pHdr;
  1052. #ifdef UNIX
  1053.     /* wait for shared memory to be initialized */
  1054.     if (!BP_MASTER && bpAlive (bs) == ERROR)
  1055. return (ERROR);
  1056. #endif /* UNIX */
  1057.     pCpu = &pHdr->hdr_cpuDesc [bs->bs_procNum];
  1058.     bs->bs_pFreeRing = ItoKval (pHdr->hdr_pFreeRing, RING *, bs->bs_pAnchor);
  1059.     bs->bs_pInputRing= ItoKval(pHdr->hdr_cpuDesc[bs->bs_procNum].cd_pInputRing,
  1060.        RING *, bs->bs_pAnchor);
  1061.     /* fill in Ethernet address, which is the backplane Ethernet address with
  1062.      * our processor number as the last byte. */
  1063. #ifdef UNIX
  1064.     bcopy ((char *) pHdr->hdr_enetAdrs,
  1065.     (char *) bs->bs_enaddr.ether_addr_octet, 6);
  1066.     bs->bs_enaddr.ether_addr_octet [4] = unit;
  1067.     bs->bs_enaddr.ether_addr_octet [5] = (char) bs->bs_procNum;
  1068. #else /* UNIX */
  1069.     bcopy ((char *) pHdr->hdr_enetAdrs, (char *) bs->bs_enaddr, 6);
  1070.     bs->bs_enaddr [4] = unit;
  1071.     bs->bs_enaddr [5] = (char) bs->bs_procNum;
  1072. #endif /* UNIX */
  1073.     /* check that our input buffer was established
  1074.      * (in case NCPU < our cpu < MAXCPU) */
  1075.     if (pCpu->cd_pInputRing == NULL)
  1076. return (ERROR);
  1077.     /* fill in our info in the CPU descriptor in shared memory */
  1078.     pCpu->cd_unit = unit; /* set our internal unit num */
  1079.     /* tell others how to interrupt us */
  1080.     pCpu->cd_intType = BP_HTONL(bs->bs_intType);
  1081.     pCpu->cd_intArg1 = BP_HTONL(bs->bs_intArg1);
  1082.     pCpu->cd_intArg2 = BP_HTONL(bs->bs_intArg2);
  1083.     pCpu->cd_intArg3 = BP_HTONL(bs->bs_intArg3);
  1084.     /* connect and enable our interprocessor interrupt */
  1085.     if (DEBUG_OPTION_1)
  1086. printf ("bp%d: connecting...n", unit);
  1087.     if (bpConnect (bs, unit) != OK || bpIntEnable (bs) != OK)
  1088. return (ERROR);
  1089.     /* tell others we're here now */
  1090.     pCpu->cd_active = TRUE;
  1091.     if ((bs->bs_if.if_flags & IFF_RUNNING) == 0)
  1092. bs->bs_if.if_flags |= IFF_UP | IFF_RUNNING;
  1093.     return (OK);
  1094.     }
  1095. /*******************************************************************************
  1096. *
  1097. * bpintr - interrupt handler
  1098. *
  1099. * RETURNS: N/A
  1100. *
  1101. * NOMANUAL
  1102. */
  1103. void bpintr
  1104.     (
  1105.     int unit
  1106.     )
  1107.     {
  1108.     FAST BP_SOFTC *bs = BP_SOFTC_P [unit];
  1109.     if (bs != NULL && bs->bs_pInputRing != NULL) /* input ring exists? */
  1110. {
  1111. #ifndef UNIX
  1112. bpIntAck (bs);
  1113. #endif /* UNIX */
  1114. if (!bs->bs_readPending)
  1115.     {
  1116.     bs->bs_readPending = TRUE;
  1117. #ifdef UNIX
  1118.     bpReadAll (unit);
  1119. #else /* UNIX */
  1120.     (void) netJobAdd ((FUNCPTR)bpReadAll, unit, 0,0,0,0); /* read from input ring */
  1121. #endif /* UNIX */
  1122.     }
  1123. }
  1124.     }
  1125. /*******************************************************************************
  1126. *
  1127. * bpReadAll -
  1128. */
  1129. LOCAL void bpReadAll
  1130.     (
  1131.     int unit
  1132.     )
  1133.     {
  1134.     FAST BP_SOFTC *bs = BP_SOFTC_P [unit];
  1135.     FAST BUF_NODE *pBufNode;
  1136.     bs->bs_readPending = FALSE;
  1137.     while ((pBufNode = (BUF_NODE *) ringget ((RING *) bs->bs_pInputRing)) != 0)
  1138. {
  1139. #ifdef UNIX
  1140. bpRead (bs, ItoKval (pBufNode, BUF_NODE *, bs->bs_pAnchor));
  1141. (void) ringput (bs->bs_pFreeRing, (int) pBufNode);
  1142. #else /* UNIX */
  1143. if (bpRead (bs, ItoKval (pBufNode, BUF_NODE *, bs->bs_pAnchor),
  1144.     pBufNode) == OK)
  1145.     (void) ringput ((RING *) bs->bs_pFreeRing, (int) pBufNode);
  1146. #endif /* UNIX */
  1147. }
  1148.     }
  1149. /*******************************************************************************
  1150. *
  1151. * bpRead -
  1152. *
  1153. * NOMANUAL
  1154. */
  1155. #ifdef UNIX
  1156. LOCAL void bpRead (bs, pBufNode)
  1157.     BP_SOFTC *bs;
  1158.     BUF_NODE *pBufNode;
  1159. #else /* UNIX */
  1160. LOCAL STATUS bpRead
  1161.     (
  1162.     BP_SOFTC *bs,
  1163.     BUF_NODE *pBufNode,
  1164.     BUF_NODE *pBufNodeOrig
  1165.     )
  1166. #endif  /* UNIX */
  1167.     {
  1168.     FAST struct ether_header *eh;
  1169.     FAST struct mbuf  *m;
  1170.     int  len;
  1171.     int  off;
  1172.     FAST unsigned char  *pData;
  1173.     STATUS  retval;
  1174. #ifdef BSD43_DRIVER
  1175.     u_short ether_type;
  1176. #endif
  1177.     retval = OK;
  1178.     bs->bs_if.if_ipackets++; /* count input packets */
  1179.     /* get length and pointer to packet */
  1180.     len = (int) (BP_NTOHS (pBufNode->b_len));
  1181.     eh = ItoKval (pBufNode->b_addr, struct ether_header *, bs->bs_pAnchor);
  1182. #ifndef UNIX
  1183.     /* call input hook if any */
  1184.     if ((etherInputHookRtn != NULL) &&
  1185. (* etherInputHookRtn) (&bs->bs_if, (char *)eh, BP_NTOHS(pBufNode->b_len)))
  1186. return (retval); /* input hook has already processed packet */
  1187. #endif /* UNIX */
  1188.     len -= SIZEOF_ETHERHEADER;
  1189.     pData = ((unsigned char *) eh) + SIZEOF_ETHERHEADER;
  1190. #ifdef UNIX
  1191.     check_trailer (eh, pData, &len, &off);
  1192.     if (len == 0)
  1193. return;
  1194.     m = copy_to_mbufs (pData, len, off);
  1195.     if (m != NULL)
  1196. do_protocol (eh, m, &bs->bs_ac, len);
  1197.     else
  1198.         bs->bs_if.if_ierrors++;     /* bump error count */
  1199. #else /* UNIX */
  1200. #ifdef BSD43_DRIVER
  1201.     check_trailer (eh, pData, &len, &off, &bs->bs_if);
  1202.     if (len == 0)
  1203. return (retval);
  1204.     ether_type = eh->ether_type;
  1205. #endif
  1206.     m = copy_to_mbufs (pData, len, off, &bs->bs_if);
  1207.     if (m != NULL)
  1208. #ifdef BSD43_DRIVER
  1209.         do_protocol_with_type (ether_type, m, &bs->bs_ac, len);
  1210. #else
  1211.         do_protocol (eh, m, &bs->bs_ac, len);
  1212. #endif
  1213.     else
  1214.         bs->bs_if.if_ierrors++;     /* bump error count */
  1215.          
  1216.     return (retval);
  1217. #endif /* UNIX */
  1218.     }
  1219. /*******************************************************************************
  1220. *
  1221. * bpStart -
  1222. *
  1223. * NOMANUAL
  1224. */
  1225. #ifdef UNIX
  1226. LOCAL void bpStart (dev)
  1227.     dev_t dev;
  1228. #else /* UNIX */
  1229. #ifdef BSD43_DRIVER
  1230. LOCAL void bpStart
  1231.     (
  1232.     int unit
  1233.     )
  1234. #else
  1235. LOCAL void bpStart
  1236.     (
  1237.     BP_SOFTC *  bs
  1238.     )
  1239. #endif    /* BSD43_DRIVER */
  1240. #endif  /* UNIX */
  1241.     {
  1242. #ifdef UNIX
  1243.     int unit = minor (dev);
  1244. #endif /* UNIX */
  1245. #if defined (BSD43_DRIVER) || defined (UNIX)
  1246.     FAST BP_SOFTC *bs = BP_SOFTC_P [unit];
  1247. #endif
  1248.     FAST struct mbuf *m;
  1249.     while (bs->bs_if.if_snd.ifq_head)               /* while queue not empty */
  1250.         {
  1251.         IF_DEQUEUE(&bs->bs_if.if_snd, m);           /* get next from queue */
  1252.         if (bpPut (bs, m) == ERROR)                 /* if couldn't send */
  1253.             {
  1254. #if defined (BSD43_DRIVER) || defined (UNIX)    
  1255.              /* vxWorks BSD 4.4 ether_output() doesn't bump statistic. */
  1256.             bs->bs_if.if_opackets--;                /* it wasn't sent! */
  1257. #endif
  1258.             bs->bs_if.if_oerrors++;                 /* it was an error */
  1259.             m_freem (m);                            /* free the mbufs */
  1260.             }
  1261. #if !defined (BSD43_DRIVER) && !defined (UNIX)
  1262.         else
  1263.             /* bump statistic for BSD 4.4 vxWorks driver. */
  1264.             bs->bs_if.if_opackets++;   
  1265. #endif
  1266.         }
  1267.     }
  1268. #if defined (BSD43_DRIVER) || defined (UNIX)
  1269. /*******************************************************************************
  1270. *
  1271. * bpOutput - net output routine
  1272. *
  1273. * Encapsulate a packet of type family for the local net.
  1274. * Use trailer local net encapsulation if enough data in first
  1275. * packet leaves a multiple of 512 bytes of data in remainder.
  1276. *
  1277. * RETURNS: 0 if successful, errno otherwise (as per network requirements)
  1278. */
  1279. LOCAL int bpOutput
  1280.     (
  1281.     struct ifnet *ifp,
  1282.     struct mbuf *m0,
  1283.     struct sockaddr *dst
  1284.     )
  1285.     {
  1286. #ifdef UNIX
  1287.     return (ether_output (ifp, m0, dst, bpStart,
  1288.     &(BP_SOFTC_P [ifp->if_unit])->bs_ac));
  1289. #else /* UNIX */
  1290.     return (ether_output (ifp, m0, dst, (FUNCPTR)bpStart,
  1291.     &BP_SOFTC_P [ifp->if_unit]->bs_ac));
  1292. #endif /* UNIX */
  1293.     }
  1294. #endif
  1295. /*******************************************************************************
  1296. *
  1297. * bpPut - copy from mbuf chain to shared memory buffer
  1298. *
  1299. * RETURNS: OK or ERROR if no room left in free ring
  1300. */
  1301. LOCAL STATUS bpPut
  1302.     (
  1303.     FAST BP_SOFTC       *bs,
  1304.     FAST struct mbuf    *m
  1305.     )
  1306.     {
  1307.     FAST BUF_NODE  *pBufNode;
  1308.     u_char  *bufStart;
  1309.     int len;
  1310.     if ((pBufNode = (BUF_NODE *) ringget ((RING *) bs->bs_pFreeRing)) == NULL)
  1311. return (ERROR);
  1312.     pBufNode = ItoKval (pBufNode, BUF_NODE *, bs->bs_pAnchor);
  1313.     bufStart = ItoKval (pBufNode->b_addr, u_char *, bs->bs_pAnchor);
  1314. #ifdef UNIX
  1315.     len = copy_from_mbufs (bufStart, m, len);
  1316. #else /* UNIX */
  1317.     copy_from_mbufs (bufStart, m, len);
  1318. #endif /* UNIX */
  1319.     len = max (MINPKTSIZE, len);
  1320.     pBufNode->b_len = BP_HTONS (len);
  1321. #ifndef UNIX
  1322.     /* call output hook if any */
  1323.     if ((etherOutputHookRtn != NULL) &&
  1324. (* etherOutputHookRtn) (&bs->bs_if, bufStart, pBufNode->b_len))
  1325. return (OK); /* output hook has already processed packet */
  1326. #endif /* UNIX */
  1327.     /* send to specified processor:
  1328.      * proc number is in last byte of Ethernet address
  1329.      */
  1330.     bpXmit (bs, pBufNode, (int) ((struct ether_header *)
  1331. #ifdef UNIX
  1332.        (bufStart))->ether_dhost.ether_addr_octet[5], bs->bs_procNum);
  1333. #else /* UNIX */
  1334.        (bufStart))->ether_dhost[5], bs->bs_procNum);
  1335. #endif /* UNIX */
  1336.     return (OK);
  1337.     }
  1338. /*******************************************************************************
  1339. *
  1340. * bpXmit - transmit buffer
  1341. */
  1342. LOCAL void bpXmit
  1343.     (
  1344.     FAST BP_SOFTC *bs,
  1345.     BUF_NODE *pBufNode,
  1346.     int destProcNum,    /* destination CPU */
  1347.     int srcProcNum      /* originator */
  1348.     )
  1349.     {
  1350.     BP_ANCHOR *pAnchor = bs->bs_pAnchor;
  1351.     u_char *buf;
  1352.     FAST CPU_DESC *pCpu;
  1353.     FAST BUF_NODE *pBufNode0;
  1354.     if (destProcNum < 0 || destProcNum >= MAXCPU)
  1355. {
  1356. /* broadcast to all CPUs on network */
  1357. buf = ItoKval (pBufNode->b_addr, u_char *, pAnchor);
  1358. for (destProcNum = MAXCPU - 1; destProcNum >= 0; --destProcNum)
  1359.     {
  1360.     pCpu = &bs->bs_pHdr->hdr_cpuDesc[destProcNum];
  1361.     if (DEBUG_OPTION_3)
  1362. dbgprintf ("bp: broadcast packet from %dn", srcProcNum, 0, 0, 0, 0, 0);
  1363.     if (!pCpu->cd_active)
  1364. continue;
  1365.     if ((pBufNode0 = (BUF_NODE *) ringget ((RING *) bs->bs_pFreeRing))
  1366.             == NULL)
  1367. break;
  1368.     pBufNode0 = ItoKval (pBufNode0, BUF_NODE *, pAnchor);
  1369.             pBufNode0->b_len = pBufNode->b_len;
  1370.     bcopy ((caddr_t) buf,
  1371.    (caddr_t) ItoKval (pBufNode0->b_addr, u_char *, pAnchor),
  1372.                    BP_NTOHS (pBufNode->b_len));
  1373.     if (ringput (ItoKval (pCpu->cd_pInputRing, RING *, pAnchor),
  1374.      KtoIval (pBufNode0, int, pAnchor)) == 0)
  1375. {
  1376. /* if input ring was full, then put bufNode back on free ring */
  1377. if (DEBUG_OPTION_2)
  1378.     dbgprintf ("bp: dropped packetn", 0,0,0,0,0,0);
  1379. (void)ringput ((RING *) bs->bs_pFreeRing,
  1380.        KtoIval (pBufNode0, int, pAnchor));
  1381. }
  1382.     else
  1383. {
  1384. /* if input ring was empty, then interrupt destination CPU */
  1385. bpIntGen (pCpu, srcProcNum);
  1386. }
  1387.     }
  1388. (void) ringput ((RING *) bs->bs_pFreeRing,
  1389.                     KtoIval (pBufNode, int, pAnchor));
  1390. }
  1391.     else
  1392. {
  1393. pCpu = &bs->bs_pHdr->hdr_cpuDesc [destProcNum];
  1394. if (DEBUG_OPTION_3)
  1395.     dbgprintf ("bp: packet from %d for %dn", srcProcNum, destProcNum, 0, 0, 0, 0);
  1396. if (!pCpu->cd_active)
  1397.     (void) ringput ((RING *) bs->bs_pFreeRing,
  1398.                         KtoIval (pBufNode, int, pAnchor));
  1399. else if (ringput (ItoKval (pCpu->cd_pInputRing, RING *, pAnchor),
  1400.           KtoIval (pBufNode, int, pAnchor)) == 0)
  1401.     {
  1402.     /* input ring was full, then put bufNode back on free ring */
  1403.     if (DEBUG_OPTION_2)
  1404. dbgprintf ("bp: dropped packetn", 0,0,0,0,0,0);
  1405.     (void) ringput ((RING *) bs->bs_pFreeRing,
  1406.     KtoIval (pBufNode, int, pAnchor));
  1407.     }
  1408. else
  1409.     {
  1410.     /* input ring had room, then interrupt destination CPU */
  1411.     bpIntGen (pCpu, srcProcNum);
  1412.     }
  1413. }
  1414.     }
  1415. #ifdef UNIX
  1416. /*******************************************************************************
  1417. *
  1418. * bpPollUnix - UNIX backplane poll
  1419. *
  1420. * This routine is called by UNIX's timeout routine to poll the
  1421. * backplane input rings for this CPU.
  1422. */
  1423. LOCAL void bpPollUnix ()
  1424.     {
  1425.     FAST int unit;
  1426.     for (unit = 0; unit < NBP; unit++)
  1427. {
  1428. /* if header structure non-zero then unit is initialized */
  1429. if (bp_softc[unit].bs_pHdr)
  1430.     bpintr (unit);
  1431. }
  1432.     /* loop forever, with a delay of 1 */
  1433.     timeout (bpPollUnix, (caddr_t)0, 1);
  1434.     }
  1435. #else /* UNIX */
  1436. /*******************************************************************************
  1437. *
  1438. * bpPollTask - backplane poll task
  1439. *
  1440. * This routine is spawned as task to poll the backplane input rings for
  1441. * this CPU.  It is only used if no backplane interrupt mechanism is
  1442. * used.
  1443. *
  1444. * NOMANUAL
  1445. */
  1446. void bpPollTask (void)
  1447.     {
  1448.     FAST int unit;
  1449.     FAST BP_SOFTC *bs;
  1450.     FOREVER
  1451. {
  1452. for (unit = 0; unit < NBP; unit++)
  1453.     {
  1454.     bs = BP_SOFTC_P [unit];
  1455.     if (bs != NULL && !bs->bs_readPending)
  1456. {
  1457. bs->bs_readPending = TRUE;
  1458. if (bs->bs_pInputRing != NULL)
  1459.     (void) netJobAdd ((FUNCPTR)bpReadAll, unit,0,0,0,0);
  1460. }
  1461.     }
  1462. }
  1463.     }
  1464. /*******************************************************************************
  1465. *
  1466. * bpIntAck - acknowledge our backplane interrupt
  1467. */
  1468. LOCAL void bpIntAck
  1469.     (
  1470.     FAST BP_SOFTC *bs
  1471.     )
  1472.     {
  1473.     switch (bs->bs_intType)
  1474. {
  1475. case BP_INT_NONE:
  1476. case BP_INT_MAILBOX_1:
  1477. case BP_INT_MAILBOX_2:
  1478. case BP_INT_MAILBOX_4:
  1479. case BP_INT_MAILBOX_R1:
  1480. case BP_INT_MAILBOX_R2:
  1481. case BP_INT_MAILBOX_R4:
  1482.     break;
  1483. /* bus interrupt:
  1484.  *   arg1 = level
  1485.  *   arg2 = vector
  1486.  */
  1487. case BP_INT_BUS:
  1488.     sysBusIntAck (bs->bs_intArg1);
  1489.     break;
  1490. }
  1491.     }
  1492. #endif /* UNIX */
  1493. /*******************************************************************************
  1494. *
  1495. * bpConnect - connect to our backplane using the requested interrupt type
  1496. *
  1497. * RETURNS: OK or ERROR if interrupt type not supported
  1498. */
  1499. LOCAL STATUS bpConnect
  1500.     (
  1501.     FAST BP_SOFTC *bs,
  1502.     FAST int unit
  1503.     )
  1504.     {
  1505.     STATUS status;
  1506.     switch (bs->bs_intType)
  1507. {
  1508. case BP_INT_NONE:
  1509. /* no interprocessor interrupt - spawn background polling task */
  1510. #ifdef UNIX
  1511.     {
  1512.     static BOOL bpIsPolling = FALSE;
  1513.     if (!bpIsPolling)
  1514. {
  1515. bpIsPolling = TRUE;
  1516. timeout (bpPollUnix, (caddr_t)0, 1);
  1517. }
  1518.     status = OK;
  1519.     }
  1520. #else /* UNIX */
  1521.     bpPollTaskId = taskSpawn ("bpPollTask", bpPollTaskPriority,
  1522.       bpPollTaskOptions, bpPollTaskStackSize,
  1523.       (FUNCPTR) bpPollTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  1524.     status = bpPollTaskId == ERROR ? ERROR : OK;
  1525. #endif /* UNIX */
  1526.     break;
  1527. case BP_INT_MAILBOX_1:
  1528. case BP_INT_MAILBOX_2:
  1529. case BP_INT_MAILBOX_4:
  1530. case BP_INT_MAILBOX_R1:
  1531. case BP_INT_MAILBOX_R2:
  1532. case BP_INT_MAILBOX_R4:
  1533. /* interrupt by mailbox (write to bus address):
  1534.  *   arg1 = bus address space
  1535.  *   arg2 = address
  1536.  *   arg3 = value
  1537.  */
  1538. #ifdef UNIX
  1539.     printf ("bp%d: bpConnect interrupt type not implementedn", unit);
  1540.     status = ERROR;
  1541. #else /* UNIX */
  1542.     status = sysMailboxConnect ((FUNCPTR)bpintr, unit);
  1543. #endif /* UNIX */
  1544.     break;
  1545. case BP_INT_BUS:
  1546. /* bus interrupt:
  1547.  *   arg1 = level
  1548.  *   arg2 = vector
  1549.  */
  1550. #ifdef UNIX
  1551.     status = OK;  /* nothing to do, done in kernel configuration */
  1552. #else /* UNIX */
  1553.     status = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (bs->bs_intArg2), bpintr, unit);
  1554. #endif /* UNIX */
  1555.     break;
  1556. default:
  1557.     printf ("bp%d: bpConnect bad interrupt type: %dn",
  1558.     unit, bs->bs_intType);
  1559.     status = ERROR;
  1560.     break;
  1561. }
  1562.     return (status);
  1563.     }
  1564. /*******************************************************************************
  1565. *
  1566. * bpIntEnable - enable our backplane interrupt
  1567. *
  1568. * RETURNS: OK or ERROR
  1569. */
  1570. LOCAL STATUS bpIntEnable
  1571.     (
  1572.     FAST BP_SOFTC *bs
  1573.     )
  1574.     {
  1575.     STATUS status;
  1576.     int unit = bs->bs_if.if_unit;
  1577.     switch (bs->bs_intType)
  1578. {
  1579. case BP_INT_NONE:
  1580.     status = OK; /* no interrupt (polling) */
  1581.     break;
  1582. case BP_INT_MAILBOX_1:
  1583. case BP_INT_MAILBOX_2:
  1584. case BP_INT_MAILBOX_4:
  1585. case BP_INT_MAILBOX_R1:
  1586. case BP_INT_MAILBOX_R2:
  1587. case BP_INT_MAILBOX_R4:
  1588. /* interrupt by mailbox (write to bus address):
  1589.  *   arg1 = bus address space
  1590.  *   arg2 = address
  1591.  *   arg3 = value
  1592.  */
  1593. #ifdef UNIX
  1594.     status = ERROR;
  1595.     printf ("bp%d: bpIntEnable interrupt type 0x%x not implementedn",
  1596.     unit, bs->bs_intType);
  1597. #else /* UNIX */
  1598.     status = sysMailboxEnable ((char *) bs->bs_intArg2);
  1599.     if (status == ERROR)
  1600. printf ("bp%d: error enabling mailbox interrupt addr 0x%x.n",
  1601.   unit, bs->bs_intArg2);
  1602. #endif /* UNIX */
  1603.     break;
  1604. case BP_INT_BUS:
  1605. /* bus interrupt:
  1606.  *   arg1 = level
  1607.  *   arg2 = vector
  1608.  */
  1609. #ifdef UNIX
  1610.     status = OK;  /* nothing to do */
  1611. #else /* UNIX */
  1612.     status = sysIntEnable (bs->bs_intArg1);
  1613.     if (status == ERROR)
  1614. printf ("bp%d: error enabling bus interrupt level %d.n",
  1615.   unit, bs->bs_intArg1);
  1616. #endif /* UNIX */
  1617.     break;
  1618. default:
  1619.     printf ("bp%d: bpIntEnable bad interrupt type: %dn",
  1620.     unit, bs->bs_intType);
  1621.     status = ERROR;
  1622.     break;
  1623. }
  1624.     return (status);
  1625.     }
  1626. /*******************************************************************************
  1627. *
  1628. * bpIntGen - interrupt another CPU
  1629. */
  1630. LOCAL void bpIntGen
  1631.     (
  1632.     FAST CPU_DESC *pCpu,        /* ptr to descriptor of CPU to interrupt */
  1633.     int srcProcNum              /* our procNum on this network */
  1634.     )
  1635.     {
  1636.     char *pMailbox;
  1637.     int intType;
  1638.     /* if we're trying to interrupt ourself (a bad idea on some CPUs (is20))
  1639.      * simply invoke the interrupt handler */
  1640.     if (BP_NTOHL(pCpu->cd_cpuNum) == srcProcNum)
  1641. {
  1642. /* read input ring */
  1643. #ifdef UNIX
  1644. bpReadAll (pCpu->cd_unit);
  1645. #else /* UNIX */
  1646. (void) netJobAdd ((FUNCPTR)bpReadAll, pCpu->cd_unit, 0,0,0,0);
  1647. #endif /* UNIX */
  1648. return;
  1649. }
  1650.     switch (intType = BP_NTOHL(pCpu->cd_intType))
  1651. {
  1652. case BP_INT_NONE:
  1653.     /* no interrupt (CPU is polling) */
  1654.     break;
  1655. case BP_INT_MAILBOX_1:
  1656. case BP_INT_MAILBOX_R1:
  1657. /* interrupt by mailbox (read/write to bus address):
  1658.  *   arg1 = bus address space
  1659.  *   arg2 = address
  1660.  *   arg3 = value
  1661.  */
  1662.     if (sysBusToLocalAdrs (BP_NTOHL(pCpu->cd_intArg1),
  1663.    (char *) BP_NTOHL(pCpu->cd_intArg2),
  1664.    &pMailbox) == OK)
  1665. {
  1666. #ifdef UNIX
  1667. bpPoke (pMailbox, intType, BP_NTOHL(pCpu->cd_intArg3),
  1668. BP_NTOHL(pCpu->cd_cpuNum));
  1669. #else /* UNIX */
  1670. if (intType == BP_INT_MAILBOX_R1)
  1671.     bpBitBucket = * (char *)pMailbox;
  1672. else
  1673.     *pMailbox = BP_NTOHL(pCpu->cd_intArg3);
  1674. #endif /* UNIX */
  1675. }
  1676.     else
  1677. {
  1678. logMsg ("bp%d: bpIntGen bad mailbox interrupt, addr space = 0x%x, addr = 0x%xn",
  1679.      pCpu->cd_unit, BP_NTOHL(pCpu->cd_intArg1),
  1680.      BP_NTOHL(pCpu->cd_intArg2), 0,0,0);
  1681. }
  1682.     break;
  1683. case BP_INT_MAILBOX_2:
  1684. case BP_INT_MAILBOX_R2:
  1685.     if (sysBusToLocalAdrs (BP_NTOHL(pCpu->cd_intArg1),
  1686.    (char *) BP_NTOHL(pCpu->cd_intArg2),
  1687.    &pMailbox) == OK)
  1688. {
  1689. #ifdef UNIX
  1690. bpPoke (pMailbox, intType, BP_NTOHL(pCpu->cd_intArg3),
  1691. BP_NTOHL(pCpu->cd_cpuNum));
  1692. #else /* UNIX */
  1693. if (intType == BP_INT_MAILBOX_R2)
  1694.     bpBitBucket = * (short *)pMailbox;
  1695. else
  1696.     * (short *) pMailbox = BP_NTOHL(pCpu->cd_intArg3);
  1697. #endif /* UNIX */
  1698. }
  1699.     else
  1700. {
  1701. logMsg (
  1702.     "bp%d: bpIntGen bad mailbox interrupt, addr space = 0x%x, addr = 0x%xn",
  1703.      pCpu->cd_unit, BP_NTOHL(pCpu->cd_intArg1),
  1704.      BP_NTOHL(pCpu->cd_intArg2), 0, 0, 0);
  1705. }
  1706.     break;
  1707. case BP_INT_MAILBOX_4:
  1708. case BP_INT_MAILBOX_R4:
  1709.     if (sysBusToLocalAdrs (BP_NTOHL(pCpu->cd_intArg1),
  1710.    (char *) BP_NTOHL(pCpu->cd_intArg2),
  1711.    &pMailbox) == OK)
  1712. {
  1713. #ifdef UNIX
  1714. bpPoke (pMailbox, intType, BP_NTOHL(pCpu->cd_intArg3),
  1715. BP_NTOHL(pCpu->cd_cpuNum));
  1716. #else /* UNIX */
  1717. if (intType == BP_INT_MAILBOX_R4)
  1718.     bpBitBucket = * (long *)pMailbox;
  1719. else
  1720.     * (long *) pMailbox = BP_NTOHL(pCpu->cd_intArg3);
  1721. #endif /* UNIX */
  1722. }
  1723.     else
  1724. {
  1725. logMsg (
  1726.     "bp%d: bpIntGen bad mailbox interrupt, addr space = 0x%x, addr = 0x%xn",
  1727.      pCpu->cd_unit, BP_NTOHL(pCpu->cd_intArg1),
  1728.      BP_NTOHL(pCpu->cd_intArg2), 0, 0, 0);
  1729. }
  1730.     break;
  1731. case BP_INT_BUS:
  1732. /* bus interrupt:
  1733.  *   arg1 = level
  1734.  *   arg2 = vector
  1735.  */
  1736. #ifndef UNIX
  1737.     if (sysBusIntGen (BP_NTOHL(pCpu->cd_intArg1),
  1738. BP_NTOHL(pCpu->cd_intArg2)) == ERROR)
  1739. {
  1740. logMsg (
  1741. "bp%d: bpIntGen interrupt failed (level=%d vector=0x%x)n",
  1742.      pCpu->cd_unit, BP_NTOHL(pCpu->cd_intArg1),
  1743.      BP_NTOHL(pCpu->cd_intArg2), 0, 0, 0);
  1744. }
  1745.     break;
  1746. #endif /* UNIX */
  1747. /* UNIX drops through */
  1748. default:
  1749.     logMsg ("bp%d: bpIntGen bad interrupt type: proc = %d, type = %dn",
  1750.      pCpu->cd_unit, BP_NTOHL(pCpu->cd_cpuNum),
  1751.      intType, 0, 0, 0);
  1752.     break;
  1753. }
  1754.     }
  1755. #ifdef UNIX
  1756. /********************************************************************************
  1757. * sysBusToLocalAdrs - convert bus address to local address
  1758. *
  1759. * Given a VME memory address, this routine returns the local address
  1760. * that would have to be accessed to get to that byte.
  1761. *
  1762. * RETURNS: OK, or ERROR if the address space is unknown.
  1763. *
  1764. * SEE ALSO: sysLocalToBusAdrs()
  1765. *
  1766. * NOMANUAL
  1767. */
  1768. STATUS sysBusToLocalAdrs (adrsSpace, busAdrs, pLocalAdrs)
  1769.     int adrsSpace;      /* bus address space in which busAdrs resides,     */
  1770.                         /* use address modifier codes as defined in vme.h, */
  1771.                         /* such as VME_AM_STD_SUP_DATA                     */
  1772.     char *busAdrs;      /* bus address to convert                          */
  1773.     char **pLocalAdrs;  /* where to return local address                   */
  1774.     {
  1775.     switch (adrsSpace)
  1776.         {
  1777.         case VME_AM_SUP_SHORT_IO:
  1778.         case VME_AM_USR_SHORT_IO:
  1779.             *pLocalAdrs = (char *) (0xffff0000 | (int) busAdrs);
  1780.             return (OK);
  1781.         case VME_AM_STD_SUP_ASCENDING:
  1782.         case VME_AM_STD_SUP_PGM:
  1783.         case VME_AM_STD_SUP_DATA:
  1784.         case VME_AM_STD_USR_ASCENDING:
  1785.         case VME_AM_STD_USR_PGM:
  1786.         case VME_AM_STD_USR_DATA:
  1787.             *pLocalAdrs = (char *) (0xff000000 | (int) busAdrs);
  1788.             return (OK);
  1789.         case VME_AM_EXT_SUP_ASCENDING:
  1790.         case VME_AM_EXT_SUP_PGM:
  1791.         case VME_AM_EXT_SUP_DATA:
  1792.         case VME_AM_EXT_USR_ASCENDING:
  1793.         case VME_AM_EXT_USR_PGM:
  1794.         case VME_AM_EXT_USR_DATA:
  1795.             *pLocalAdrs = busAdrs; /* XXX check if on board memory? */
  1796.             return (OK);
  1797.         default:
  1798.             return (ERROR);
  1799.         }
  1800.     }
  1801. #endif /* UNIX */
  1802. /*******************************************************************************
  1803. *
  1804. * bpHeartbeat -
  1805. */
  1806. LOCAL void bpHeartbeat
  1807.     (
  1808.     FAST BP_ANCHOR *pAnchor
  1809.     )
  1810.     {
  1811.     pAnchor->an_heartbeat =
  1812. (UINT)BP_HTONL((UINT)BP_NTOHL(pAnchor->an_heartbeat) + 1);
  1813. #ifdef UNIX
  1814.     timeout (bpHeartbeat, (caddr_t) pAnchor, bpHeartbeatRate);
  1815. #else /* UNIX */
  1816.     wdStart (pAnchor->an_wdog, bpHeartbeatRate, (FUNCPTR) bpHeartbeat,
  1817.              (int) pAnchor);
  1818. #endif /* UNIX */
  1819.     }
  1820. /*******************************************************************************
  1821. *
  1822. * bpSizeMem - size shared memory pool
  1823. *
  1824. * RETURNS: amount of available memory
  1825. */
  1826. LOCAL int bpSizeMem
  1827.     (
  1828.     caddr_t memAdrs,    /* address of start of pool to start probing */
  1829.     int memSize         /* max size of memory pool */
  1830.     )
  1831.     {
  1832.     FAST int size;
  1833.     for (size = 0; size < memSize; size += 4096)
  1834. {
  1835. #ifdef UNIX
  1836.         if ((*bpProbeType) ((char *)(memAdrs + size), 0) == -1)
  1837. #else /* UNIX */
  1838. char bitBucket;
  1839. if (vxMemProbe (memAdrs + size, bpProbeType, 1, &bitBucket) != OK)
  1840. #endif /* UNIX */
  1841.     break;
  1842. }
  1843.     if (bpParity)
  1844. bzero (memAdrs, memSize);
  1845.     /* return the amount of memory found */
  1846.     return (size);
  1847.     }
  1848. /*******************************************************************************
  1849. *
  1850. * bpIoctl - process an ioctl request
  1851. *
  1852. * RETURNS: 0 if successful, errno otherwise (as per network requirements)
  1853. */
  1854. LOCAL int bpIoctl
  1855.     (
  1856.     FAST struct ifnet *pIf,
  1857.     int cmd,
  1858.     caddr_t data
  1859.     )
  1860.     {
  1861.     int error = 0;
  1862.     int unit  = pIf->if_unit;
  1863.     FAST BP_SOFTC *bs = BP_SOFTC_P [unit];
  1864.     int level = splimp ();
  1865.     switch (cmd)
  1866. {
  1867. case SIOCSIFADDR:
  1868. #ifdef UNIX
  1869.             error = set_if_addr (pIf, data, &bs->bs_enaddr);
  1870. #else /* UNIX */
  1871.             ((struct arpcom *)pIf)->ac_ipaddr = IA_SIN (data)->sin_addr;
  1872.             arpwhohas (pIf, &IA_SIN (data)->sin_addr);
  1873. #endif /* UNIX */
  1874.     break;
  1875. case SIOCGIFADDR:
  1876. #ifdef UNIX
  1877.     bcopy ((caddr_t) &bs->bs_enaddr,
  1878.   (caddr_t) &((struct ifreq *)data)->ifr_addr.sa_data[0],
  1879.   sizeof (struct ether_addr));
  1880. #else /* UNIX */
  1881.     bcopy ((caddr_t) bs->bs_enaddr,
  1882.   (caddr_t) &((struct ifreq *)data)->ifr_addr.sa_data[0],
  1883.   6);
  1884. #endif /* UNIX */
  1885.     break;
  1886.         case SIOCGIFFLAGS:
  1887.             *(short *)data = pIf->if_flags;
  1888.             break;
  1889.         case SIOCSIFFLAGS:
  1890.             {
  1891.             short flags = *(short *)data;
  1892.             /* Sanity check - make sure IFF_RUNNING and IFF_UP flags match. */
  1893.               
  1894.             if (pIf->if_flags & IFF_UP)
  1895.                 flags |= (IFF_UP|IFF_RUNNING);
  1896.             else
  1897.                 flags &= ~(IFF_UP|IFF_RUNNING);
  1898.             pIf->if_flags = flags;
  1899.     }
  1900. break;
  1901. default:
  1902.     printf ("bp%d: ioctl 0x%x not implementedn", unit, cmd);
  1903.     error = EINVAL;
  1904.     break;
  1905. }
  1906.     (void) splx (level);
  1907.     return (error);
  1908.     }
  1909. /*******************************************************************************
  1910. *
  1911. * ringinit -
  1912. *
  1913. * Initialize the ring pointed to by "rp" to contain "size" slots.
  1914. * The ring is set up to be empty and unlocked.
  1915. * Size had better be a power of 2!
  1916. */
  1917. LOCAL void ringinit
  1918.     (
  1919.     FAST RING *rp,
  1920.     short size
  1921.     )
  1922.     {
  1923.     rp->r_tas = rp->r_rdidx = rp->r_wrtidx = 0;
  1924.     rp->r_size = BP_HTONS(size);
  1925.     }
  1926. /*******************************************************************************
  1927. *
  1928. * ringput -
  1929. *
  1930. * Add a new entry "v" to the ring "rp".
  1931. * Returns 0 if ring was full, else the new number of entries in the ring.
  1932. * Uses test-and-set routine, allowing multi-processor interlocked access
  1933. * to the ring IF the ring is in VME memory.
  1934. * Masks all interrupts, in order to prevent reentrancy and to
  1935. * minimize ring lockout.
  1936. *
  1937. * RETURNS: new number of entries, or 0 if ring was full
  1938. */
  1939. LOCAL int ringput
  1940.     (
  1941.     FAST RING *rp,
  1942.     int v
  1943.     )
  1944.     {
  1945.     FAST int x = DELAY_COUNT; /* don't wait forever for lock */
  1946.     FAST int s;
  1947.     for (;;)
  1948. {
  1949. /* disable interrupts, then lock the ring */
  1950. s = intLock ();
  1951. if (TAS(&rp->r_tas))
  1952.     break;
  1953. intUnlock (s);
  1954. if (--x == 0)
  1955.     return (0); /* ring is stuck! */
  1956. }
  1957.     if ((x = (BP_NTOHS(rp->r_wrtidx) + 1) &
  1958.     (BP_NTOHS(rp->r_size) - 1)) != BP_NTOHS(rp->r_rdidx))
  1959. {
  1960. rp->r_slot[BP_NTOHS(rp->r_wrtidx)] = v;
  1961. rp->r_wrtidx = BP_HTONS(x);
  1962. } /* if x == rdidx then ring is full */
  1963.     if ((x -= BP_NTOHS(rp->r_rdidx)) < 0)
  1964. x += BP_NTOHS(rp->r_size);
  1965. #if     (CPU_FAMILY==MIPS)
  1966.     TAS_CLEAR(rp->r_tas);               /* unlock ring */
  1967. #else   /* CPU_FAMILY==MIPS */
  1968.     rp->r_tas = 0;                      /* unlock ring */
  1969. #endif  /* CPU_FAMILY==MIPS */
  1970.     intUnlock (s);
  1971.     return (x);
  1972.     }
  1973. /*******************************************************************************
  1974. *
  1975. * ringget -
  1976. *
  1977. * Extract next entry from the ring "rp".
  1978. * Uses test-and-set routine, allowing multi-processor interlocked access
  1979. * to the ring IF the ring is in VME memory.
  1980. * Masks all interrupts, in order to prevent reentrancy and to
  1981. * minimize ring lockout.
  1982. *
  1983. * RETURNS: 0 if ring is empty, else the extracted entry
  1984. */
  1985. LOCAL int ringget
  1986.     (
  1987.     FAST RING *rp
  1988.     )
  1989.     {
  1990.     FAST int x = DELAY_COUNT; /* don't wait forever for lock */
  1991.     FAST int s;
  1992.     for (;;)
  1993. {
  1994. /* disable interrupts, then lock the ring */
  1995. s = intLock ();
  1996. if (TAS(&rp->r_tas))
  1997.     break;
  1998. intUnlock (s);
  1999. if (--x == 0)
  2000.     return (0); /* ring is stuck! */
  2001. }
  2002.     if (rp->r_rdidx != rp->r_wrtidx)
  2003. {
  2004. x = rp->r_slot[BP_NTOHS(rp->r_rdidx)];
  2005. rp->r_rdidx = BP_HTONS(
  2006. (BP_NTOHS(rp->r_rdidx) + 1) & (BP_NTOHS(rp->r_size) - 1));
  2007. }
  2008.     else
  2009. x = 0;
  2010. #if     (CPU_FAMILY==MIPS)
  2011.     TAS_CLEAR(rp->r_tas);               /* unlock ring */
  2012. #else   /* CPU_FAMILY==MIPS */
  2013.     rp->r_tas = 0;                      /* unlock ring */
  2014. #endif  /* CPU_FAMILY==MIPS */
  2015.     intUnlock (s);
  2016.     return (x);
  2017.     }
  2018. /******************************************************************************
  2019. *
  2020. * ringcount - get number of entries in ring
  2021. */
  2022. LOCAL int ringcount
  2023.     (
  2024.     FAST RING *pRing
  2025.     )
  2026.     {
  2027.     int n = BP_NTOHS(pRing->r_wrtidx) - BP_NTOHS(pRing->r_rdidx);
  2028.     if (n < 0)
  2029. n += BP_NTOHS(pRing->r_size);
  2030.     return (n);
  2031.     }
  2032. /********************************************************************************
  2033. * vxTasac - test-and-set-and-check
  2034. *
  2035. * This routine provides quick and dirty test and set when hardware isn't up to
  2036. * the tas.
  2037. *
  2038. * RETURNS:
  2039. *   TRUE if value had been not set (but now is),
  2040. *   FALSE if value was already set.
  2041. */
  2042. LOCAL BOOL vxTasac
  2043.     (
  2044.     FAST char *address          /* address to be tested */
  2045.     )
  2046.     {
  2047.     FAST int tasWait = 10;
  2048.     FAST int count;
  2049.     FAST int value = 0x80 + sysProcNumGet ();
  2050.     int oldLevel = intLock ();
  2051.     /* check for lock available */
  2052.     if (*address != 0)
  2053.         {
  2054.         intUnlock (oldLevel);
  2055.         return (FALSE);
  2056.         }
  2057.     /* lock available - take it */
  2058.     *address = value;
  2059.     /* check that we got it and nobody stepped on it, several times */
  2060.     for (count = 0; count < tasWait; count++)
  2061.         {
  2062.         if (* (unsigned char *) address != value)
  2063.             {
  2064.             intUnlock (oldLevel);
  2065.             return (FALSE);
  2066.             }
  2067.         }
  2068.     intUnlock (oldLevel);
  2069.     return (TRUE);
  2070.     }
  2071. /*******************************************************************************
  2072. *
  2073. * bpShow - display information about the backplane network
  2074. *
  2075. * This routine shows information about the different CPUs configured
  2076. * in the backplane network.
  2077. *
  2078. * EXAMPLE
  2079. * .CS
  2080. *     -> bpShow
  2081. *     Anchor at 0x800000
  2082. *     heartbeat = 705, header at 0x800010, free pkts = 237.
  2083. *
  2084. *     cpu int type    arg1       arg2       arg3    queued pkts rd index
  2085. *     --- -------- ---------- ---------- ---------- ----------- --------
  2086. *      0  poll            0x0        0x0        0x0       0        27
  2087. *      1  poll            0x0        0x0        0x0       0        11
  2088. *      2  bus-int         0x3       0xc9        0x0       0        9
  2089. *      3  mbox-2         0x2d     0x8000        0x0       0        1
  2090. *
  2091. *     input packets = 192     output packets = 164
  2092. *     output errors = 0       collisions = 0
  2093. *     value = 1 = 0x1
  2094. * .CE
  2095. *
  2096. * RETURNS: N/A
  2097. */
  2098. void bpShow
  2099.     (
  2100.     char *bpName,       /* backplane interface name (NULL == "bp0") */
  2101.     BOOL zero           /* TRUE = zap totals */
  2102.     )
  2103.     {
  2104.     FAST BP_SOFTC *bs;
  2105.     FAST BP_ANCHOR *pAnchor;
  2106.     FAST BP_HEADER *pHdr;
  2107.     FAST CPU_DESC *pCpu;
  2108.     RING *pRing;
  2109.     FAST int cpuNum;
  2110.     /* use "bp0" if no interface name specified */
  2111.     if (bpName == NULL)
  2112. bpName = "bp0";
  2113.     /* get pointer to interface descriptor */
  2114.     if ((bs = (BP_SOFTC *) ifunit (bpName)) == NULL)
  2115. {
  2116. printf ("interface %s not attached.n", bpName);
  2117. return;
  2118. }
  2119.     /* check validity of anchor */
  2120.     pAnchor = bs->bs_pAnchor;
  2121.     printf ("Anchor at 0x%x", (int)pAnchor);
  2122. #ifdef UNIX
  2123.     if (peek ((short *)pAnchor) == -1)
  2124. #else /* UNIX */
  2125.     if (vxMemProbe ((char *) pAnchor, O_RDONLY, 4, (char *) &bpBitBucket) != OK)
  2126. #endif /* UNIX */
  2127. {
  2128. printf (", UNREADABLEn");
  2129. return;
  2130. }
  2131.     if (BP_NTOHL(pAnchor->an_ready) != BP_READY)
  2132. {
  2133. if (BP_NTOHL(pAnchor->an_ready) == BP_READY_SOFT_TAS)
  2134.     printf (", SOFT TASn");
  2135. else
  2136.     {
  2137.     printf (", UNINITIALIZEDn");
  2138.     return;
  2139.     }
  2140. }
  2141.     if (bpAlive (bs) == ERROR)
  2142. {
  2143. printf (", NO HEARTBEATn");
  2144. return;
  2145. }
  2146.     /* anchor valid - print out anchor and header info */
  2147.     pHdr = ItoKval (((BP_ANCHOR *)pAnchor)->an_pHdr, BP_HEADER *, pAnchor);
  2148.     printf (" heartbeat = %d, header at 0x%x, free pkts = %d.nn",
  2149.     (int)BP_NTOHL(pAnchor->an_heartbeat),
  2150.     (int)pHdr, ringcount ((RING *)(bs->bs_pFreeRing)));
  2151.     /* print out info for each CPU */
  2152.     printf (
  2153. "cpu int type    arg1       arg2       arg3    queued pkts rd indexn");
  2154.     printf (
  2155. "--- -------- ---------- ---------- ---------- ----------- --------n");
  2156.     for (cpuNum = 0; cpuNum < MAXCPU; ++cpuNum)
  2157. {
  2158. pCpu = &pHdr->hdr_cpuDesc[cpuNum];
  2159. if (pCpu->cd_active)
  2160.     {
  2161.     printf ("%2d  ", cpuNum);
  2162.     switch (BP_NTOHL(pCpu->cd_intType))
  2163. {
  2164. case BP_INT_NONE: printf ("poll    "); break;
  2165. case BP_INT_MAILBOX_1: printf ("mbox-1  "); break;
  2166. case BP_INT_MAILBOX_2: printf ("mbox-2  "); break;
  2167. case BP_INT_MAILBOX_4: printf ("mbox-4  "); break;
  2168. case BP_INT_MAILBOX_R1: printf ("mbox-1r "); break;
  2169. case BP_INT_MAILBOX_R2: printf ("mbox-2r "); break;
  2170. case BP_INT_MAILBOX_R4: printf ("mbox-4r "); break;
  2171. case BP_INT_BUS: printf ("bus-int "); break;
  2172. default:
  2173. printf ("%#8x",BP_NTOHL(pCpu->cd_intType));
  2174. break;
  2175. }
  2176.     printf (" %#10x %#10x %#10x",
  2177.     BP_NTOHL(pCpu->cd_intArg1),
  2178.     BP_NTOHL(pCpu->cd_intArg2),
  2179.     BP_NTOHL(pCpu->cd_intArg3));
  2180.     pRing = ItoKval (pCpu->cd_pInputRing, RING *, pAnchor);
  2181.     printf ("     %3d       %3dn", ringcount (pRing), BP_NTOHS(pRing->r_rdidx));
  2182.     }
  2183. }
  2184.     printf ("ninput packets = %3ld  ", bs->bs_if.if_ipackets);
  2185.     if (zero)
  2186. bs->bs_if.if_ipackets = 0;
  2187.     printf ("output packets = %3ldn", bs->bs_if.if_opackets);
  2188.     if (zero)
  2189. bs->bs_if.if_opackets = 0;
  2190.     printf ("output errors = %3ld  ", bs->bs_if.if_oerrors);
  2191.     if (zero)
  2192. bs->bs_if.if_oerrors = 0;
  2193.     printf ("collisions     = %3ldn", bs->bs_if.if_collisions);
  2194.     if (zero)
  2195. bs->bs_if.if_collisions = 0;
  2196.     }
  2197. #ifndef UNIX
  2198. /******************************************************************************
  2199. *
  2200. * bpSlotCheck - check if a CPU is being serviced by a backplane unit
  2201. *
  2202. * This routine can be used on a backplane master CPU to find out
  2203. * if a particular slave CPU is being serviced by a particular
  2204. * backplane device unit.
  2205. *
  2206. * NOMANUAL
  2207. */
  2208. BOOL bpSlotCheck
  2209.     (
  2210.     int unit,                   /* backplane device unit */
  2211.     int slot                    /* CPU number  */
  2212.     )
  2213.     {
  2214.     FAST BP_SOFTC  *bs;
  2215.     FAST BP_ANCHOR *pAnchor;
  2216.     FAST BP_HEADER *pHdr;
  2217.     FAST CPU_DESC  *pCpu;
  2218.     char    devName [10];
  2219.     sprintf (devName, "bp%d", unit);
  2220.     bs = (BP_SOFTC *) ifunit (devName);
  2221.     if (bs == NULL)
  2222.         return (FALSE);
  2223.     pAnchor = bs->bs_pAnchor;
  2224.     if (vxMemProbe ((char *) pAnchor, O_RDONLY, 4, (char *) &bpBitBucket) != OK)
  2225.         return (FALSE);
  2226.     if (BP_NTOHL(pAnchor->an_ready) != BP_READY &&
  2227. BP_NTOHL(pAnchor->an_ready) != BP_READY_SOFT_TAS)
  2228.         return (FALSE);
  2229.     pHdr = ItoKval (((BP_ANCHOR *)pAnchor)->an_pHdr, BP_HEADER *, pAnchor);
  2230.     pCpu = &pHdr->hdr_cpuDesc [slot];
  2231.     if (pCpu->cd_active)
  2232.         return (TRUE);
  2233.     return (FALSE);
  2234.     }
  2235. #endif