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

VxWorks

开发平台:

C/C++

  1. /* if_ilac.c - AMD 79C900 ILACC Ethernet network interface driver */
  2. /* Copyright 1989-1997 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01e,15jul97,spm  added ARP request to SIOCSIFADDR ioctl handler
  8. 01d,07apr97,spm  code cleanup and upgraded to BSD 4.4
  9. 01c,25nov96,dat  coding standards, documentation
  10. 01b,09jan95,caf  added intConnect() call to ilacattach().
  11. 01a,02jan95,kat  written.
  12. */
  13. /*
  14. DESCRIPTION:
  15. */
  16. /* includes */
  17. #include "vxWorks.h"
  18. #include "net/mbuf.h"
  19. #include "net/protosw.h"
  20. #include "sys/ioctl.h"
  21. #include "sys/socket.h"
  22. #include "errnoLib.h"
  23. #include "net/if.h"
  24. #include "net/route.h"
  25. #include "netinet/in.h"
  26. #include "netinet/in_systm.h"
  27. #include "netinet/ip.h"
  28. #include "netinet/ip_var.h"
  29. #include "netinet/in_var.h"
  30. #include "netinet/if_ether.h"
  31. #include "etherLib.h"
  32. #include "vme.h"
  33. #include "iv.h"
  34. #include "iosLib.h"
  35. #include "ioLib.h"
  36. #include "memLib.h"
  37. #include "net/systm.h"
  38. #include "net/if_subr.h"
  39. #include "sysLib.h"
  40. #include "vxLib.h"
  41. #include "stdio.h"
  42. #include "intLib.h"
  43. #include "logLib.h"
  44. #include "string.h"
  45. #include "netLib.h"
  46. #include "stdlib.h"
  47. #include "drv/netif/if_ilac.h"
  48. #define MINPKTSIZE   60
  49. typedef struct /* SHIFT_BUFFER */
  50.     { 
  51.     char     dummy_space[16]; 
  52.     TM_DESC  shift_tring[XMIT_DES_CNT]; 
  53.     char     shift_xmit_buf[XMIT_DES_CNT * ROUND_BUF_SIZE]; 
  54.     RM_DESC  shift_rring[RECV_DES_CNT]; 
  55.     char     shift_recv_buf[RECV_DES_CNT * ROUND_BUF_SIZE]; 
  56.     INIT_BLK shift_init_blk;
  57.     } SHIFT_BUFFER;
  58. LOCAL SHIFT_BUFFER shift_buffer;
  59. typedef struct mbuf MBUF;
  60. typedef struct arpcom IDR; /* Interface Data Record wrapper */
  61. typedef struct ifnet IFNET; /* real Interface Data Record */
  62. typedef struct sockaddr SOCK;
  63. typedef struct ether_header ETH_HDR;
  64. IMPORT unsigned char ilacEnetAddr[6];
  65. typedef struct /* DRV_CTRL */
  66.     {
  67.     IDR           idr;          /* interface data record */
  68.     int           unit;         /* which unit are we */
  69.     ILAC_DEVICE  *addr;         /* address of physical device */
  70.     int           recvIndex;    /* next receive buffer */
  71.     int           xmitIndex;    /* next transmit buffer */
  72.     TM_DESC      *tranRing; /* transmit message descriptors */
  73.     RM_DESC      *recvRing; /* receive message descriptors */
  74.     INIT_BLK     *initBlk; /* initialization block */
  75.     char         *xmitBuf; /* transmit buffers */
  76.     char         *recvBuf; /* receive buffers */
  77.     volatile BOOL rcvHandling;  /* flag, indicates netTask active */
  78.     BOOL          attached;     /* TRUE if attach() has succeeded */
  79.     } DRV_CTRL;
  80. LOCAL DRV_CTRL drvCtrl[1];
  81. LOCAL STATUS ilacInit(int unit, char *eaddr);
  82. LOCAL void   ilacInt(int unit);
  83. /* ether_attach functions */
  84. LOCAL int    ilacIoctl(IDR *pIDR, int cmd, caddr_t data);
  85. #ifdef BSD43_DRIVER
  86. LOCAL STATUS ilacOutput(IDR *pIDR, MBUF *pMbuf, SOCK *pDest);
  87. #endif
  88. LOCAL STATUS ilacReset(int unit);
  89. LOCAL void   ilacHandleRecvInt (DRV_CTRL *pDrv);
  90. #ifdef BSD43_DRIVER
  91. LOCAL void   ilacTxStartup(int unit);
  92. #else
  93. LOCAL void   ilacTxStartup (DRV_CTRL *pDrv);
  94. #endif
  95. LOCAL STATUS ilacReceive(DRV_CTRL *pDrv, unsigned char *buf, int *len);
  96. LOCAL STATUS ilacTransmit(DRV_CTRL *pDrv, unsigned char *buf, int len);
  97. /*******************************************************************************
  98. *
  99. * ilacattach - attach ilac driver network system
  100. *
  101. * RETURNS:
  102. */
  103. STATUS ilacattach
  104.     (
  105.     int unit,
  106.     char *addrs,
  107.     int ivec
  108.     )
  109.     {
  110.     DRV_CTRL *pDrv = &drvCtrl[unit];
  111.     
  112.     if (pDrv->attached)
  113. {
  114.         return OK;
  115. }
  116. #ifdef BSD43_DRIVER
  117.     ether_attach(&pDrv->idr.ac_if, unit, "ilac", (FUNCPTR) NULL,
  118.  (FUNCPTR) ilacIoctl, (FUNCPTR) ilacOutput,
  119.  (FUNCPTR) ilacReset);
  120. #else
  121.     ether_attach (
  122.                  &pDrv->idr.ac_if, 
  123.                  unit, 
  124.                  "ilac", 
  125.                  (FUNCPTR) NULL,
  126.  (FUNCPTR) ilacIoctl, 
  127.                  (FUNCPTR) ether_output,
  128.                  (FUNCPTR) ilacReset
  129.                  );
  130.     pDrv->idr.ac_if.if_start = (FUNCPTR)ilacTxStartup;
  131. #endif
  132.     pDrv->addr = (ILAC_DEVICE *)addrs;
  133.     /* connect the interrupt handler */
  134.     (void) intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (ivec),
  135.                        (VOIDFUNCPTR)ilacInt, NULL);
  136.     ilacInit(unit, (char *)pDrv->idr.ac_enaddr);
  137.     
  138.     pDrv->idr.ac_if.if_flags |= IFF_UP | IFF_RUNNING | IFF_NOTRAILERS;
  139.     pDrv->rcvHandling = FALSE;
  140.     /* Set our success indicator */
  141.     pDrv->attached = TRUE;
  142.     return OK;
  143.     }
  144. /*******************************************************************************
  145. *
  146. * ilacInit - initialize an ILAC device 
  147. *
  148. * RETURNS:
  149. */
  150. LOCAL STATUS ilacInit
  151.     (
  152.     int unit,
  153.     char *ethernet_num
  154.     )
  155.     { 
  156.     int          i;
  157.     unsigned int csr0; 
  158.     unsigned int count; 
  159.     DRV_CTRL    *pDrv = &drvCtrl[unit];
  160.     ILAC_DEVICE *ilac = pDrv->addr;
  161.     
  162.     /* Set init bit in CSR0 register */
  163.     ilac->rap = 0;
  164.     ilac->rdp = CSR0_STOP;
  165.     
  166.     pDrv->tranRing =
  167. (TM_DESC *) (((unsigned int)&shift_buffer.shift_tring[0]) & 0xFFFFFFF0);
  168.     pDrv->recvRing =
  169. (RM_DESC *) (((unsigned int)&shift_buffer.shift_rring[0]) & 0xFFFFFFF0);
  170.     pDrv->xmitBuf =
  171. (char *) (((unsigned int)&shift_buffer.shift_xmit_buf[0]) & 0xFFFFFFF0);
  172.     pDrv->recvBuf =
  173. (char *) (((unsigned int)&shift_buffer.shift_recv_buf[0]) & 0xFFFFFFF0);
  174.     pDrv->initBlk =
  175. (INIT_BLK *)(((unsigned int)&shift_buffer.shift_init_blk) & 0xFFFFFFF0);
  176.     
  177.     /* Setup the transmit descriptors */ 
  178.     for(i = 0; i < XMIT_DES_CNT; i++)
  179. {
  180. pDrv->tranRing[i].addr =
  181. (unsigned long)&pDrv->xmitBuf[i * ROUND_BUF_SIZE];
  182. pDrv->tranRing[i].error = 0;
  183. pDrv->tranRing[i].status = (TST_STP | TST_ENP);
  184. }
  185.     /* Setup the receive descriptors */ 
  186.     for(i = 0; i < RECV_DES_CNT; i++)
  187. {
  188. pDrv->recvRing[i].addr = 
  189. (unsigned long)&pDrv->recvBuf[i * ROUND_BUF_SIZE];
  190. pDrv->recvRing[i].bcnt = -(ROUND_BUF_SIZE);
  191. pDrv->recvRing[i].mcnt = 0;
  192. pDrv->recvRing[i].flags = RFLG_OWN; /* give buffer to ilac */
  193. }
  194.     /* set up ilac init block */
  195.     pDrv->initBlk->mode = 0; /* IBM_PROM; 0 */
  196.     pDrv->initBlk->rlen = L2RECV_DES_CNT;
  197.     
  198.     /* Set the receive descriptor ring address */
  199.     pDrv->initBlk->rdra = (unsigned long)pDrv->recvRing;
  200.     
  201.     /* Set the transmit descriptor ring length */
  202.     pDrv->initBlk->tlen = L2XMIT_DES_CNT;
  203.     /* Set the tranmit descriptor ring address */
  204.     pDrv->initBlk->tdra = (unsigned long)pDrv->tranRing;
  205.     
  206.     /* grab the hardware enet address */
  207.     for (i = 0; i < 6; i++)
  208. {
  209. ethernet_num[i] = ilacEnetAddr[i];
  210.     pDrv->initBlk->padr[3] = ethernet_num[0];
  211.     pDrv->initBlk->padr[2] = ethernet_num[1];
  212.     pDrv->initBlk->padr[1] = ethernet_num[2];
  213.     pDrv->initBlk->padr[0] = ethernet_num[3];
  214.     pDrv->initBlk->padr[7] = ethernet_num[4];
  215.     pDrv->initBlk->padr[6] = ethernet_num[5];
  216.     /* CSR4 controls selected diagnostic functions, microprocessor bus  */
  217.     /* acquisition and DMA signaling */
  218.     ilac->rap = 4;
  219.     ilac->rdp = CSR4_BACON_68K | CSR4_TXSTRTM | CSR4_LBDM;
  220.     ilac->rap = 3;
  221.     ilac->rdp = CSR3_ACON | CSR3_IDONM | CSR3_TINTM;
  222.  
  223.     /* CSR2 must contain the high order 16 bits of the first word in */
  224.     /* the initialization block */
  225.     ilac->rap = 2;
  226.     ilac->rdp = (((int)pDrv->initBlk & 0xff0000) >> 16);
  227.     
  228.     /* CSR1 must contain the low order 16 bits of the first word in */
  229.     /* the initialization block */
  230.     ilac->rap = 1;
  231.     ilac->rdp = ((int)pDrv->initBlk & 0xffff);
  232.     
  233.     ilac->rap = 0;
  234.     ilac->rdp = CSR0_INIT | CSR0_INEA;
  235.     
  236.     count = 0;  
  237.     while (!((csr0 = ilac->rdp) & CSR0_IDON) && count < INIT_TMO)
  238. {
  239. count++;
  240. }
  241.     if (count >= INIT_TMO)
  242. {
  243. printf ("ilac: INIT timeout: CSR0 = 0x%xn", (unsigned short)csr0);
  244. return ERROR;
  245. }
  246.     else
  247. {
  248. count = 0;
  249. ilac->rdp = CSR0_STRT | CSR0_INEA;
  250. while (!((csr0 = ilac->rdp) & (CSR0_RXON | CSR0_TXON)) &&
  251. count < STRT_TMO)
  252.     {
  253.     count++;
  254.     }
  255. if (count >= STRT_TMO)
  256.     {
  257.     printf ("ilac: STRT timeout: CSR0 = 0x%xn", (unsigned short)csr0);
  258.     return ERROR;
  259.     }
  260. }
  261.     
  262.     pDrv->recvIndex = 0; 
  263.     pDrv->xmitIndex = 0;
  264.     
  265.     return OK;
  266.     }
  267. /*******************************************************************************
  268. *
  269. * ilacInt - ILAC interrupt service routine
  270. *
  271. * RETURNS:
  272. */
  273. LOCAL void ilacInt
  274.     (
  275.     int unit
  276.     )
  277.     {
  278.     int       status;
  279.     DRV_CTRL *pDrv = (DRV_CTRL *)&drvCtrl[0];
  280.     /* get csr0 */
  281.     pDrv->addr->rap = 0;
  282.     status = pDrv->addr->rdp;
  283.     
  284.     /* ack interrupt and reenable */
  285.     pDrv->addr->rap = 0;
  286.     pDrv->addr->rdp = CSR0_ACKINT | CSR0_INEA;
  287.     
  288.     if (status & CSR0_RINT) /* handle receive interrput */
  289. {
  290. if (!(pDrv->rcvHandling))
  291.     {
  292.             pDrv->rcvHandling = TRUE;
  293.             netJobAdd ( (FUNCPTR)ilacHandleRecvInt, (int)pDrv, 0, 0, 0, 0);
  294.     }
  295. }
  296.     else
  297. {
  298. logMsg("ilac0: got unexpected interrupt: 0x%4xn", status,
  299. 0, 0, 0, 0, 0);
  300. }
  301.     }
  302. /*******************************************************************************
  303. *
  304. * ilacIoctl - ILAC control functions
  305. *
  306. * RETURNS:
  307. */
  308. LOCAL int ilacIoctl
  309.     (
  310.     IDR *pIDR,
  311.     int cmd,
  312.     caddr_t data
  313.     )
  314.     {
  315.     STATUS error = OK;
  316.     
  317.     switch (cmd)
  318. {
  319.         case SIOCSIFADDR:
  320.            ((struct arpcom *)pIDR)->ac_ipaddr = IA_SIN (data)->sin_addr;
  321.             arpwhohas (pIDR, &IA_SIN (data)->sin_addr);
  322.             break;
  323.     
  324.         case SIOCSIFFLAGS:
  325.             break;
  326.         default:
  327.             error = EINVAL;
  328. }
  329.     
  330.     return error;
  331.     }
  332. #ifdef BSD43_DRIVER
  333. /*******************************************************************************
  334. *
  335. * ilacOutput - packet transmit routine
  336. *
  337. * RETURNS:
  338. */
  339. LOCAL STATUS ilacOutput
  340.     (
  341.     IDR *pIDR,
  342.     MBUF *pMbuf,
  343.     SOCK *pDest
  344.     )
  345.     {
  346.     return ether_output ((IFNET *)pIDR, pMbuf, pDest, (FUNCPTR) ilacTxStartup,
  347. pIDR);
  348.     }
  349. #endif
  350. /*******************************************************************************
  351. *
  352. * ilacReset - ILAC reset device routine
  353. *
  354. *
  355. * RETURNS:
  356. */
  357. LOCAL STATUS ilacReset
  358.     (
  359.     int unit
  360.     )
  361.     {
  362.     logMsg ("ilac%d: reset called", unit, 0, 0, 0, 0, 0);
  363.     
  364.     return OK;
  365.     }
  366. /*******************************************************************************
  367. *
  368. * ilacHandleRecvInt - task level portion of packet receive
  369. *
  370. * RETURNS:
  371. */
  372. LOCAL void ilacHandleRecvInt
  373.     (
  374.     DRV_CTRL *pDrv
  375.     )
  376.     {
  377.     MBUF *  pMbuf;
  378.     int  length;
  379.     unsigned char  packet[ROUND_BUF_SIZE];
  380.     ETH_HDR *  pEh;
  381.     unsigned char *  pData;
  382. #ifdef BSD43_DRIVER
  383.     unsigned short  type;
  384. #endif
  385.     pDrv->rcvHandling = TRUE;
  386.     while (ilacReceive (pDrv, packet, &length) != ERROR)
  387. {
  388. ++pDrv->idr.ac_if.if_ipackets;
  389. pEh = (ETH_HDR *)packet;
  390. if ( (etherInputHookRtn != NULL) &&
  391.      (*etherInputHookRtn) (&pDrv->idr, (char *)pEh, length))
  392.             continue;
  393.         length -= sizeof (ETH_HDR);
  394. pData = (unsigned char *) (packet + sizeof (ETH_HDR));
  395. #ifdef BSD43_DRIVER
  396.         type = ntohs (pEh->ether_type);
  397. #endif
  398.         pMbuf = copy_to_mbufs (pData, length, 0, &pDrv->idr);
  399.         if (pMbuf != NULL)
  400. #ifdef BSD43_DRIVER
  401.             do_protocol_with_type(type, pMbuf, &pDrv->idr, length);
  402. #else
  403.             do_protocol (pEh, pMbuf, &pDrv->idr, length);
  404. #endif
  405.         }
  406.     pDrv->rcvHandling = FALSE; 
  407.     }
  408. /*******************************************************************************
  409. *
  410. * ilacTxStartup - startup transmitter
  411. *
  412. *
  413. * RETURNS:
  414. */
  415. #ifdef BSD43_DRIVER
  416. LOCAL void ilacTxStartup
  417.     (
  418.     int unit
  419.     )
  420.     {
  421.     DRV_CTRL     *pDrv = &drvCtrl[unit];
  422. #else
  423. LOCAL void ilacTxStartup
  424.     (
  425.     DRV_CTRL     *pDrv
  426.     )
  427.     {
  428. #endif
  429.     MBUF         *pMbuf;
  430.     int           length;
  431.     unsigned char packet[ROUND_BUF_SIZE];
  432.     STATUS result;
  433.     /*
  434.      * Loop until there are no more packets ready to send or we
  435.      * have insufficient resources left to send another one.
  436.      */
  437.     
  438.     while (pDrv->idr.ac_if.if_snd.ifq_head)
  439. {
  440.         IF_DEQUEUE (&pDrv->idr.ac_if.if_snd, pMbuf);  /* dequeue a packet */
  441.         copy_from_mbufs ( (ETH_HDR *)packet, pMbuf, length);
  442.         if ( (etherOutputHookRtn != NULL) &&
  443.              (*etherOutputHookRtn) (&pDrv->idr, (ETH_HDR *)packet, length))
  444.             continue;
  445.         result = ilacTransmit (pDrv, packet, length);
  446.         if (result == ERROR)
  447.             pDrv->idr.ac_if.if_oerrors++;
  448. #ifndef BSD43_DRIVER    /* BSD 4.4 ether_output doesn't bump statistic. */
  449.         else
  450.             pDrv->idr.ac_if.if_opackets++; 
  451. #endif
  452. }
  453.     }
  454. /*******************************************************************************
  455. *
  456. * ilacReceive - receive packet
  457. *
  458. *
  459. * RETURNS:
  460. */
  461. LOCAL STATUS ilacReceive
  462.     (
  463.     DRV_CTRL *pDrv,
  464.     unsigned char *packet,
  465.     int *len
  466.     )
  467.     {
  468.     RM_DESC      *rmd = (RM_DESC *)&pDrv->recvRing[pDrv->recvIndex]; 
  469.     
  470.     if (rmd->flags & RFLG_OWN)
  471. {
  472. return ERROR;
  473.     if (rmd->flags & RFLG_ERR)
  474. pDrv->recvIndex++; 
  475. pDrv->recvIndex %= RECV_DES_CNT;
  476. rmd->flags |= RFLG_OWN;
  477. logMsg("ilac0: recv ERROR: 0x%xn", rmd->flags, 0, 0, 0, 0, 0); 
  478. return ERROR;  
  479. }
  480.     
  481.     *len = rmd->mcnt; 
  482.     
  483.     bcopy((char *)rmd->addr, (char *)packet, *len);
  484.     pDrv->recvIndex++; 
  485.     pDrv->recvIndex %= RECV_DES_CNT;
  486.     /* ilac can have this buffer back again */
  487.     rmd->mcnt = 0; 
  488.     rmd->flags |= RFLG_OWN;
  489.     
  490.     return OK;
  491.     } 
  492. /*******************************************************************************
  493. *
  494. * ilacTransmit - actual packet transmission
  495. *
  496. *
  497. * RETURNS:
  498. */
  499. LOCAL STATUS ilacTransmit
  500.     (
  501.     DRV_CTRL *pDrv,
  502.     unsigned char *packet,
  503.     int len
  504.     )
  505.     {
  506.     unsigned int   count;
  507.     unsigned char  status;
  508.     
  509.     TM_DESC *tmd;
  510.     tmd = (TM_DESC *)&pDrv->tranRing[pDrv->xmitIndex]; 
  511.     
  512.     bcopy ((const char *)packet, (char *)tmd->addr, len);
  513.     
  514.     len = (len < MINPKTSIZE) ? MINPKTSIZE : len;
  515.     tmd->bcnt = TBCNT_ONES | -(len);
  516.     tmd->error = 0;
  517.     tmd->status = TST_XMIT;
  518.     
  519.     count = 0;
  520.     while ( (status = tmd->status) & TST_OWN)
  521. if (count++ > XMIT_TMO)
  522.     return ERROR;
  523.     if (status & TST_ERR)
  524. {
  525. pDrv->xmitIndex++; 
  526. pDrv->xmitIndex %= XMIT_DES_CNT;
  527. if ( (tmd->error << 10) & TERR_LCAR)
  528.     logMsg ("ilac%d: lost carriern", pDrv->idr.ac_if.if_unit,
  529.     0, 0, 0, 0, 0);
  530. else
  531.     logMsg ("ilac%d: ERROR = 0x%xn", pDrv->idr.ac_if.if_unit,
  532.     tmd->error, 0, 0, 0, 0); 
  533. return ERROR;
  534. }
  535.     pDrv->xmitIndex++; 
  536.     pDrv->xmitIndex %= XMIT_DES_CNT;
  537.     return OK;
  538.     }