📄 network.c
字号:
/* uti595.c: An 82596 ethernet driver for rtems-bsd. * * $Id: network.c,v 1.6 2002/11/04 22:17:34 joel Exp $ */void dump_scb(void);void printk_time(void);#ifdef DBG_VERSION#define BREAKPOINT() asm(" int $3"); #else#define BREAKPOINT()#endif#define KERNEL/* EII: Oct 16 : Version 0.0*/#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */#define DMA_MASK_REG 0x0A#define DMA_MODE_REG 0x0B#define DMA_ENABLE 0x0#define DMA_DISABLE 0x4 struct i596_rfd *pISR_Rfd; void show_buffers (void);void show_queues(void);void outbyte(char);void dumpQ(void);#define UTI_596_ASSERT( condition, str ) { if (!( condition ) ) printk(str); }int count_rx = 0;/* static char *version = "uti596.c:v0.0 11/13/97\n"; */#include <bsp.h>#include <stdio.h>#include <stdlib.h>#include <rtems/error.h>#include <rtems/rtems_bsdnet.h>#include <sys/param.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/sockio.h>#include <net/if.h>#include <netinet/in.h>#include <netinet/if_ether.h>#include "uti596.h"#include "netexterns.h"#include <asm.h>#include <string.h>/* #include "../misc/utils.h" */static struct uti596_softc uti596_softc;static int scbStatus;static struct i596_cmd *pIsrCmd;static struct i596_rfd *pIsrRfd;/* * Initial 596 configuration */char uti596initSetup[] = { 0x0E, /* length, prefetch off ( no RBD's ) */ 0xC8, /* fifo to 8, monitor off */ 0x40, /* don't save bad frames ( was save= 80, use intel's 40 )*/ 0x2E, /* No source address insertion, 8 byte preamble */ 0x00, /* priority and backoff defaults */ 0x60, /* interframe spacing */ 0x00, /* slot time LSB */ 0xf2, /* slot time and retries */ 0x0C, /* */ 0x08, /* collision detect */ 0x40, /* minimum frame length */ 0xfb, /* tried C8 same as byte 1 in bits 6-7, else ignored*/ 0x00, 0x3f /* no multi IA */ };/* * Externally defined symbols */#define RX_BUF_COUNT 15#define TX_BUF_COUNT 4#define TX_BD_PER_BUF 4#define INTERRUPT_EVENT RTEMS_EVENT_1#define START_TRANSMIT_EVENT RTEMS_EVENT_2#define NIC_RESET_EVENT RTEMS_EVENT_3#define RBUF_SIZE 1520/* * Local Routines *//* These are extern, and non-inline for testing purposes */void uti596addCmd (struct i596_cmd *pCmd);void uti596_initMem (struct uti596_softc *); void uti596_init (void * );int uti596initRxBufs (int num);int uti596_initRFA (int num);int uti596initRxBufs (int num);static int uti596_ioctl (struct ifnet *, int, caddr_t);rtems_isr uti596DynamicInterruptHandler (rtems_vector_number);void uti596_txDaemon (void *);void uti596_rxDaemon (void *);void uti596_resetDaemon (void *);void uti596_stop (struct uti596_softc *);static void uti596_start (struct ifnet *);void uti596reset (void);void uti596_stats (struct uti596_softc *);void uti596_initialize_hardware(struct uti596_softc *);void uti596_reset_hardware(struct uti596_softc *);void uti596clearListStatus(struct i596_rfd *);void uti596addPolledCmd(struct i596_cmd *);void uti596supplyFD(struct i596_rfd *);struct i596_rfd * uti596dequeue( struct i596_rfd ** );void uti596append( struct i596_rfd ** , struct i596_rfd * ); #ifdef DEBUG_INITstatic void print_eth (unsigned char *);static void print_hdr (unsigned char *);static void print_pkt (unsigned char *);#endifvoid send_packet(struct ifnet *, struct mbuf *);#define UTI_596_IRQ 5#define UTI_596_ETH_MIN_SIZE 60/* Waits for the command word to clear. The command word is cleared AFTER the interrupt is * generated. This allows the CPU to issue the next command */#define UTI_WAIT_COMMAND_ACCEPTED(duration,function)\{ int waitcount = duration; \ while ( uti596_softc.scb.command ) \ if (--waitcount == 0) \ { \ printk("%s: i82596 timed out with status %x, cmd %x.\n", function, \ uti596_softc.scb.status, uti596_softc.scb.command); \ break; \ } \}/*************************************************************************/void uti596_request_reset(void){ rtems_status_code sc; uti596_softc.nic_reset = 0; sc = rtems_event_send(uti596_softc.resetDaemonTid, NIC_RESET_EVENT); if ( sc != RTEMS_SUCCESSFUL ) rtems_panic ("Can't notify resetDaemon: %s\n", rtems_status_text (sc));}static void uti596_maskOn(const rtems_irq_connect_data* irq){ /* * code should be moved from initialize_hardware * to this location ? */ (void) BSP_irq_enable_at_i8259s (irq->name);}static void uti596_maskOff(const rtems_irq_connect_data* irq){ /* * code should be moved from initialize_hardware * to this location ? */ (void) BSP_irq_disable_at_i8259s (irq->name);}static int uti596_isOn(const rtems_irq_connect_data* irq){ return BSP_irq_enabled_at_i8259s (irq->name);}/*********************************************************************** * Function: uti596initRFA(int num) ( New ) * * Description: * attempts to allocate and initialize ( chain together ) * the requested number of FD's * * Algorithm: * ***********************************************************************/int uti596_initRFA(int num){ struct i596_rfd *pRfd; int i = 0;#ifdef DBG_596 printf ("%s: uti596_initRFA %d.\n", num);#endif /* * Initialize the first rfd in the rfa */ pRfd = (struct i596_rfd *) calloc (1,sizeof (struct i596_rfd)); if ( !pRfd ) { printf("Can't allocate all buffers: only %d allocated\n", i); return 0; } else { uti596_softc.countRFD = 1; uti596_softc.pBeginRFA = uti596_softc.pEndRFA = pRfd; printf ( "First Rfd allocated is: %p\n", uti596_softc.pBeginRFA); } for (i = 1; i < num; i++) { pRfd = (struct i596_rfd *) calloc (1,sizeof (struct i596_rfd) ); if ( pRfd != NULL ) { uti596_softc.countRFD++; uti596_softc.pEndRFA -> next = pRfd; /* link it in */ uti596_softc.pEndRFA = pRfd; /* move the end */#ifdef DBG_596_RFA printf("Allocated RFD @ %p\n", pRfd);#endif } else { printf("Can't allocate all buffers: only %d allocated\n", i); break; } } /* end for */ uti596_softc.pEndRFA -> next = I596_NULL; UTI_596_ASSERT(uti596_softc.countRFD == RX_BUF_COUNT,"INIT:WRONG RFD COUNT\n" ); #ifdef DBG_596_RFA printf ( "Head of RFA is buffer %p\nEnd of RFA is buffer %p \n", uti596_softc.pBeginRFA, uti596_softc.pEndRFA );#endif /* initialize the Rfd's */ for ( pRfd = uti596_softc.pBeginRFA; pRfd != I596_NULL; pRfd = pRfd -> next ) { pRfd->cmd = 0x0000; pRfd->stat = 0x0000; pRfd->pRbd = I596_NULL; pRfd->count = 0; /* number of bytes in buffer: usually less than size */ pRfd->size = 1532; /* was 1532; buffer size ( All RBD ) */ if ( pRfd -> data == NULL ) printf("Can't allocate the RFD data buffer\n"); } /* mark the last FD */ uti596_softc.pEndRFA -> cmd = CMD_EOL; /* moved jan 13 from before the init stuff */#ifdef DBG_596_RFA printf ( "Head of RFA is buffer @ %p \n", uti596_softc.pBeginRFA );#endif uti596_softc.pSavedRfdQueue = uti596_softc.pEndSavedQueue = I596_NULL; /* initially empty */ uti596_softc.savedCount = 0; uti596_softc.nop.cmd.command = CmdNOp; /* initialize the nop command */ return (i); /* the number of allocated buffers */ }/*********************************************************************** * Function: uti596supplyFD * * Description: returns a buffer to the receive frame pool. * call this with Inetrrupts disabled! * * Algorithm: * ***********************************************************************/void uti596supplyFD(struct i596_rfd * pRfd ){ struct i596_rfd *pLastRfd; UTI_596_ASSERT(pRfd != I596_NULL, "Supplying NULL RFD!\n"); pRfd -> cmd = CMD_EOL; pRfd -> pRbd = I596_NULL; pRfd -> next = I596_NULL; pRfd -> stat = 0x0000; /* clear STAT_C and STAT_B bits */ /* * Check if the list is empty: */ if ( uti596_softc.pBeginRFA == I596_NULL ) { /* Init a list w/ one entry */ uti596_softc.pBeginRFA = uti596_softc.pEndRFA = pRfd; UTI_596_ASSERT(uti596_softc.countRFD == 0, "Null begin, but non-zero count\n"); if ( uti596_softc.pLastUnkRFD != I596_NULL ) printf("LastUnkRFD is NOT NULL!!\n"); uti596_softc.countRFD = 1; return; } /* * Check if the last RFD is used/read by the 596. */ pLastRfd = uti596_softc.pEndRFA; if ( pLastRfd != I596_NULL && ! (pLastRfd -> stat & ( STAT_C | STAT_B ) )) { /* C = complete, B = busy (prefetched) */ /* * Not yet too late to add it */ pLastRfd -> next = pRfd; pLastRfd -> cmd &= ~CMD_EOL; /* RESET_EL : reset EL bit to 0 */ uti596_softc.countRFD++; /* Lets assume we add it successfully If not, the RFD may be used, and may decrement countRFD < 0 !!*/ /* * Check if the last RFD was used while appending. */ if ( pLastRfd -> stat & ( STAT_C | STAT_B ) ) { /* completed or was prefetched */ /* * Either the EL bit of the last rfd has been read by the 82596, * and it will stop after reception,( true when RESET_EL not reached ) or * the EL bit was NOT read by the 82596 and it will use the linked * RFD for the next reception. ( true is RESET_EL was reached ) * So, it is unknown whether or not the linked rfd will be used. * Therefore, the end of list CANNOT be updated. */ UTI_596_ASSERT ( uti596_softc.pLastUnkRFD == I596_NULL, "Too many Unk RFD's\n" ); uti596_softc.pLastUnkRFD = pRfd; return; } else { /* * The RFD being added was not touched by the 82596 */ if (uti596_softc.pLastUnkRFD != I596_NULL ) { uti596append(&uti596_softc.pSavedRfdQueue, pRfd); /* Only here! saved Q */ uti596_softc.pEndSavedQueue = pRfd; uti596_softc.savedCount++; uti596_softc.countRFD--; } else { uti596_softc.pEndRFA = pRfd; /* the RFA has been extended */ if ( ( uti596_softc.scb.status & SCB_STAT_RNR || uti596_softc.scb.status & RU_NO_RESOURCES ) && uti596_softc.countRFD > 1 ) { /* was == 2 */ uti596_softc.pBeginRFA -> cmd &= ~CMD_EOL; /* Ensure that beginRFA is not EOL */ UTI_596_ASSERT(uti596_softc.pEndRFA -> next == I596_NULL, "supply: List buggered\n"); UTI_596_ASSERT(uti596_softc.pEndRFA -> cmd & CMD_EOL, "supply: No EOL at end.\n"); UTI_596_ASSERT(uti596_softc.scb.command == 0, "Supply: scb command must be zero\n");#ifdef DBG_START printf("Supply FD: starting receiver");#endif /* start the receiver */ UTI_596_ASSERT(uti596_softc.pBeginRFA != I596_NULL, "rx start w/ NULL begin! \n"); uti596_softc.scb.pRfd = uti596_softc.pBeginRFA; uti596_softc.scb.command = RX_START | SCB_STAT_RNR; /* Don't ack RNR! The receiver should be stopped in this case */ UTI_596_ASSERT( !(uti596_softc.scb.status & SCB_STAT_FR),"FRAME RECEIVED INT COMING!\n"); outport_byte(CHAN_ATTN, 0); } } return; } } else { /* * too late , pLastRfd in use ( or NULL ), * in either case, EL bit has been read, and RNR condition will occur */ uti596append( &uti596_softc.pSavedRfdQueue, pRfd); /* save it for RNR */ uti596_softc.pEndSavedQueue = pRfd; /* reset end of saved queue */ uti596_softc.savedCount++; return; }}static voiduti596_start (struct ifnet *ifp){ struct uti596_softc *sc = ifp->if_softc; rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); ifp->if_flags |= IFF_OACTIVE;}voiduti596_initialize_hardware(struct uti596_softc *sc){ int boguscnt = 1000; rtems_status_code status_code; printf("uti596_initialize_hardware\n"); /* reset the board */ outport_word( PORT_ADDR, 0 ); outport_word( PORT_ADDR, 0 ); uti596_softc.pScp = (struct i596_scp *) calloc(1,sizeof(struct i596_scp) + 0xf);#ifdef DBG_INIT printf("initialize_hardware:Scp address initially %p\n", sc->pScp);#endif sc->pScp = (struct i596_scp *) ((((int)uti596_softc.pScp) + 0xf) & 0xfffffff0);#ifdef DBG_INIT printf("initialize_hardware:change scp address to : %p\n",sc->pScp);#endif /* change the scp address */#ifdef DBG_INIT printf("Change the SCP address\n");#endif /* * Set the DMA mode to enable the 82596 to become a bus-master */ outport_byte(DMA_MASK_REG,DMA_DISABLE); /* disable_dma */ outport_byte(DMA_MODE_REG,DMA_MODE_CASCADE); /* set dma mode */ outport_byte(DMA_MASK_REG,DMA_ENABLE); /* enable dma */ /* reset the board */ outport_word( PORT_ADDR, 0 ); outport_word( PORT_ADDR, 0 ); outport_word(PORT_ADDR, ((((int)sc->pScp) & 0xffff) | 2 )); outport_word(PORT_ADDR, (( (int)sc->pScp) >> 16 ) & 0xffff ); /* This is linear mode, LOCK function is disabled */ sc->pScp->sysbus = 0x00540000; sc->pScp->iscp = &sc->iscp; sc->iscp.scb = &sc->scb; sc->iscp.stat = 0x0001; sc->pCmdHead = sc->scb.pCmd = I596_NULL; #ifdef DBG_596 printf("Starting i82596.\n");#endif /* Pass the scb address to the 596 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -