📄 dec21140.c
字号:
*/ status = ld_le32(tbase+memCSR5); st_le32((tbase+memCSR5), status); /* * Frame received? */ if( status & 0x000000c0 ) { sc->rxInterrupts++; rtems_event_send(rxDaemonTid, sc->ioevent); }}static rtems_isrdec21140Enet_interrupt_handler_entry(){ int i; /* ** Check all the initialized dec units for interrupt service */ for(i=0; i< NDECDRIVER; i++ ) { if( dec21140_softc[i].base ) dec21140Enet_interrupt_handler( &dec21140_softc[i] ); }}/* * Initialize the ethernet hardware */static voiddec21140Enet_initialize_hardware (struct dec21140_softc *sc){ int i,st; volatile unsigned int *tbase; volatile unsigned char *cp, *setup_frm, *eaddrs; volatile unsigned char *buffer; volatile struct MD *rmd;#ifdef DEC_DEBUG printk("dec2114x : %02x:%02x:%02x:%02x:%02x:%02x name '%s%d', io %x, mem %x, int %d\n", sc->arpcom.ac_enaddr[0], sc->arpcom.ac_enaddr[1], sc->arpcom.ac_enaddr[2], sc->arpcom.ac_enaddr[3], sc->arpcom.ac_enaddr[4], sc->arpcom.ac_enaddr[5], sc->arpcom.ac_if.if_name, sc->arpcom.ac_if.if_unit, sc->port, (unsigned) sc->base, sc->irqInfo.name );#endif tbase = sc->base; /* * WARNING : First write in CSR6 * Then Reset the chip ( 1 in CSR0) */ st_le32( (tbase+memCSR6), CSR6_INIT); st_le32( (tbase+memCSR0), RESET_CHIP); rtems_bsp_delay_in_bus_cycles(200); st_le32( (tbase+memCSR7), NO_IT); /* * Init CSR0 */ st_le32( (tbase+memCSR0), CSR0_MODE); /* * Init RX ring */ cp = (volatile unsigned char *)malloc(((sc->numRxbuffers+sc->numTxbuffers)*sizeof(struct MD)) + (sc->numTxbuffers*RBUF_SIZE) + CPU_CACHE_ALIGNMENT_FOR_BUFFER); sc->bufferBase = cp; cp += (CPU_CACHE_ALIGNMENT_FOR_BUFFER - (int)cp) & (CPU_CACHE_ALIGNMENT_FOR_BUFFER - 1);#if defined(__i386__)#ifdef PCI_BRIDGE_DOES_NOT_ENSURE_CACHE_COHERENCY_FOR_DMA if (_CPU_is_paging_enabled()) _CPU_change_memory_mapping_attribute (NULL, cp, ((sc->numRxbuffers+sc->numTxbuffers)*sizeof(struct MD)) + (sc->numTxbuffers*RBUF_SIZE), PTE_CACHE_DISABLE | PTE_WRITABLE);#endif#endif rmd = (volatile struct MD*)cp; sc->MDbase = rmd; sc->nextRxMD = sc->MDbase; buffer = cp + ((sc->numRxbuffers+sc->numTxbuffers)*sizeof(struct MD)); st_le32( (tbase+memCSR3), (long)(phys_to_bus((long)(sc->MDbase)))); for (i=0 ; i<sc->numRxbuffers; i++) { struct mbuf *m; /* allocate an mbuf for each receive descriptor */ MGETHDR (m, M_WAIT, MT_DATA); MCLGET (m, M_WAIT); m->m_pkthdr.rcvif = &sc->arpcom.ac_if; rmd->m = m; rmd->buf2 = phys_to_bus(rmd+1); rmd->buf1 = phys_to_bus(mtod(m, void *)); rmd->status = 0x80000000; rmd->counts = 0xfdc00000 | (RBUF_SIZE); rmd->next = rmd+1; rmd++; } /* * mark last RX buffer. */ sc->MDbase [sc->numRxbuffers-1].buf2 = 0; sc->MDbase [sc->numRxbuffers-1].counts = 0xfec00000 | (RBUF_SIZE); sc->MDbase [sc->numRxbuffers-1].next = sc->MDbase; /* * Init TX ring */ st_le32( (tbase+memCSR4), (long)(phys_to_bus((long)(rmd))) ); for (i=0 ; i<sc->numTxbuffers; i++){ (rmd+i)->buf2 = phys_to_bus(rmd+i+1); (rmd+i)->buf1 = phys_to_bus(buffer + (i*RBUF_SIZE)); (rmd+i)->counts = 0x01000000; (rmd+i)->status = 0x0; (rmd+i)->next = rmd+i+1; (rmd+i)->m = 0; } /* * mark last TX buffer. */ (rmd+sc->numTxbuffers-1)->buf2 = phys_to_bus(rmd); (rmd+sc->numTxbuffers-1)->next = rmd; /* * Build setup frame */ setup_frm = (volatile unsigned char *)(bus_to_phys(rmd->buf1)); eaddrs = (char *)(sc->arpcom.ac_enaddr); /* Fill the buffer with our physical address. */ for (i = 1; i < 16; i++) { *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[3]; *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[3]; *setup_frm++ = eaddrs[4]; *setup_frm++ = eaddrs[5]; *setup_frm++ = eaddrs[4]; *setup_frm++ = eaddrs[5]; } /* Add the broadcast address when doing perfect filtering */ memset((void*) setup_frm, 0xff, 12); rmd->counts = 0x09000000 | 192 ; rmd->status = 0x80000000; st_le32( (tbase+memCSR6), CSR6_INIT | CSR6_TX); st_le32( (tbase+memCSR1), 1); while (rmd->status != 0x7fffffff); rmd->counts = 0x01000000; sc->TxMD = rmd+1; sc->irqInfo.hdl = (rtems_irq_hdl)dec21140Enet_interrupt_handler_entry; sc->irqInfo.on = no_op; sc->irqInfo.off = no_op; sc->irqInfo.isOn = dec21140IsOn;#ifdef DEC_DEBUG printk( "dec2114x: Installing IRQ %d\n", sc->irqInfo.name );#endif#ifdef BSP_SHARED_HANDLER_SUPPORT st = BSP_install_rtems_shared_irq_handler( &sc->irqInfo );#else st = BSP_install_rtems_irq_handler( &sc->irqInfo );#endif if (!st) rtems_panic ("dec2114x : Interrupt name %d already in use\n", sc->irqInfo.name );}static voiddec21140_rxDaemon (void *arg){ volatile unsigned int *tbase; volatile struct MD *rmd; struct dec21140_softc *sc; struct ifnet *ifp; struct ether_header *eh; struct mbuf *m; unsigned int i,len; rtems_event_set events; for (;;) { rtems_bsdnet_event_receive( RTEMS_ALL_EVENTS, RTEMS_WAIT|RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &events); for(i=0; i< NDECDRIVER; i++ ) { sc = &dec21140_softc[i]; if( sc->base ) { if( events & sc->ioevent ) { ifp = &sc->arpcom.ac_if; tbase = sc->base; rmd = sc->nextRxMD; /* ** Read off all the packets we've received on this unit */ while((rmd->status & 0x80000000) == 0) { /* printk("unit %i rx\n", ifp->if_unit ); */ /* pass on the packet in the mbuf */ len = (rmd->status >> 16) & 0x7ff; m = (struct mbuf *)(rmd->m); m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header); eh = mtod (m, struct ether_header *); m->m_data += sizeof(struct ether_header); ether_input (ifp, eh, m); /* get a new mbuf for the 21140 */ MGETHDR (m, M_WAIT, MT_DATA); MCLGET (m, M_WAIT); m->m_pkthdr.rcvif = ifp; rmd->m = m; rmd->buf1 = phys_to_bus(mtod(m, void *)); /* mark the descriptor as ready to receive */ rmd->status = 0x80000000; rmd=rmd->next; } sc->nextRxMD = rmd; } } } }}static voidsendpacket (struct ifnet *ifp, struct mbuf *m){ struct dec21140_softc *dp = ifp->if_softc; volatile struct MD *tmd; volatile unsigned char *temp; struct mbuf *n; unsigned int len; volatile unsigned int *tbase; tbase = dp->base; /* * Waiting for Transmitter ready */ tmd = dp->TxMD; n = m; while ((tmd->status & 0x80000000) != 0) { tmd=tmd->next; } len = 0; temp = (volatile unsigned char *)(bus_to_phys(tmd->buf1)); for (;;) { len += m->m_len; memcpy((void*) temp, (char *)m->m_data, m->m_len); temp += m->m_len ; if ((m = m->m_next) == NULL) break; } if (len < ET_MINLEN) len = ET_MINLEN; tmd->counts = 0xe1000000 | (len & 0x7ff); tmd->status = 0x80000000; st_le32( (tbase+memCSR1), 0x1); m_freem(n); dp->TxMD = tmd->next;}/* * Driver transmit daemon */voiddec21140_txDaemon (void *arg){ struct dec21140_softc *sc; struct ifnet *ifp; struct mbuf *m; int i; rtems_event_set events; for (;;) { /* * Wait for packets bound for any of the dec units */ rtems_bsdnet_event_receive( RTEMS_ALL_EVENTS, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events); for(i=0; i< NDECDRIVER; i++ ) { sc = &dec21140_softc[i]; if( sc->base ) { if( events & sc->ioevent ) { ifp = &sc->arpcom.ac_if; /* * Send packets till queue is empty */ for(;;) { IF_DEQUEUE(&ifp->if_snd, m); if( !m ) break; /* printk("unit %i tx\n", ifp->if_unit ); */ sendpacket (ifp, m); } ifp->if_flags &= ~IFF_OACTIVE; } } } }}static voiddec21140_start (struct ifnet *ifp){ struct dec21140_softc *sc = ifp->if_softc; rtems_event_send( txDaemonTid, sc->ioevent ); ifp->if_flags |= IFF_OACTIVE;}/* * Initialize and start the device */static voiddec21140_init (void *arg){ struct dec21140_softc *sc = arg; struct ifnet *ifp = &sc->arpcom.ac_if; volatile unsigned int *tbase; /* * Set up DEC21140 hardware if its not already been done */ if( !sc->irqInfo.hdl ) { dec21140Enet_initialize_hardware (sc); } /* * Enable RX and TX */ tbase = sc->base; st_le32( (tbase+memCSR5), IT_SETUP); st_le32( (tbase+memCSR7), IT_SETUP); st_le32( (unsigned int*)(tbase+memCSR6), CSR6_INIT | CSR6_TXRX); /* * Tell the world that we're running. */ ifp->if_flags |= IFF_RUNNING;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -