From 031df3914990db0336a0d386fb53558b05de467e Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 23 Apr 2018 09:53:31 +0200 Subject: bsps: Move legacy network drivers to bsps This patch is a part of the BSP source reorganization. Update #3285. --- c/src/lib/libbsp/m68k/gen68360/network/network.c | 1062 ---------------------- 1 file changed, 1062 deletions(-) delete mode 100644 c/src/lib/libbsp/m68k/gen68360/network/network.c (limited to 'c/src/lib/libbsp/m68k/gen68360/network/network.c') diff --git a/c/src/lib/libbsp/m68k/gen68360/network/network.c b/c/src/lib/libbsp/m68k/gen68360/network/network.c deleted file mode 100644 index 0a038d3348..0000000000 --- a/c/src/lib/libbsp/m68k/gen68360/network/network.c +++ /dev/null @@ -1,1062 +0,0 @@ -/* - * RTEMS driver for M68360 SCC1 Ethernet - * - * W. Eric Norum - * Saskatchewan Accelerator Laboratory - * University of Saskatchewan - * Saskatoon, Saskatchewan, CANADA - * eric@skatter.usask.ca - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include - -/* - * Number of SCCs supported by this driver - */ -#define NSCCDRIVER 1 - -/* - * Default number of buffer descriptors set aside for this driver. - * The number of transmit buffer descriptors has to be quite large - * since a single frame often uses four or more buffer descriptors. - */ -#define RX_BUF_COUNT 15 -#define TX_BUF_COUNT 4 -#define TX_BD_PER_BUF 4 - -/* - * RTEMS event used by interrupt handler to signal driver tasks. - * This must not be any of the events used by the network task synchronization. - */ -#define INTERRUPT_EVENT RTEMS_EVENT_1 - -/* - * RTEMS event used to start transmit daemon. - * This must not be the same as INTERRUPT_EVENT. - */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - -/* - * Receive buffer size -- Allow for a full ethernet packet including CRC - */ -#define RBUF_SIZE 1520 - -#if (MCLBYTES < RBUF_SIZE) -# error "Driver must have MCLBYTES > RBUF_SIZE" -#endif - -/* - * Per-device data - */ -struct scc_softc { - struct arpcom arpcom; - struct mbuf **rxMbuf; - struct mbuf **txMbuf; - int acceptBroadcast; - int rxBdCount; - int txBdCount; - int txBdHead; - int txBdTail; - int txBdActiveCount; - m360BufferDescriptor_t *rxBdBase; - m360BufferDescriptor_t *txBdBase; - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - - /* - * Statistics - */ - unsigned long rxInterrupts; - unsigned long rxNotFirst; - unsigned long rxNotLast; - unsigned long rxGiant; - unsigned long rxNonOctet; - unsigned long rxRunt; - unsigned long rxBadCRC; - unsigned long rxOverrun; - unsigned long rxCollision; - - unsigned long txInterrupts; - unsigned long txDeferred; - unsigned long txHeartbeat; - unsigned long txLateCollision; - unsigned long txRetryLimit; - unsigned long txUnderrun; - unsigned long txLostCarrier; - unsigned long txRawWait; - unsigned long txCoalesced; - unsigned long txCoalesceFailed; - unsigned long txRetry; -}; -static struct scc_softc scc_softc[NSCCDRIVER]; - -extern void *_RomBase; /* From linkcmds */ - -/* - * SCC1 interrupt handler - */ -static rtems_isr -m360Enet_interrupt_handler (rtems_vector_number v) -{ - /* - * Frame received? - */ - if ((m360.scc1.sccm & 0x8) && (m360.scc1.scce & 0x8)) { - m360.scc1.scce = 0x8; - m360.scc1.sccm &= ~0x8; - scc_softc[0].rxInterrupts++; - rtems_bsdnet_event_send (scc_softc[0].rxDaemonTid, INTERRUPT_EVENT); - } - - /* - * Buffer transmitted or transmitter error? - */ - if ((m360.scc1.sccm & 0x12) && (m360.scc1.scce & 0x12)) { - m360.scc1.scce = 0x12; - m360.scc1.sccm &= ~0x12; - scc_softc[0].txInterrupts++; - rtems_bsdnet_event_send (scc_softc[0].txDaemonTid, INTERRUPT_EVENT); - } - m360.cisr = 1UL << 30; /* Clear SCC1 interrupt-in-service bit */ -} - -/* - * Initialize the ethernet hardware - */ -static void -m360Enet_initialize_hardware (struct scc_softc *sc) -{ - int i; - unsigned char *hwaddr; - rtems_status_code status; - rtems_isr_entry old_handler; - - /* - * Configure port A CLK1, CLK2, TXD1 and RXD1 pins - */ - m360.papar |= 0x303; - m360.padir &= ~0x303; - m360.paodr &= ~0x303; - - /* - * Configure port C CTS1* and CD1* pins - */ - m360.pcpar &= ~0x30; - m360.pcdir &= ~0x30; - m360.pcso |= 0x30; - - /* - * Connect CLK1 and CLK2 to SCC1 - */ - m360.sicr &= ~0xFF; - m360.sicr |= (5 << 3) | 4; - - /* - * Allocate mbuf pointers - */ - sc->rxMbuf = malloc (sc->rxBdCount * sizeof *sc->rxMbuf, M_MBUF, M_NOWAIT); - sc->txMbuf = malloc (sc->txBdCount * sizeof *sc->txMbuf, M_MBUF, M_NOWAIT); - if (!sc->rxMbuf || !sc->txMbuf) - rtems_panic ("No memory for mbuf pointers"); - - /* - * Set receiver and transmitter buffer descriptor bases - */ - sc->rxBdBase = M360AllocateBufferDescriptors(sc->rxBdCount); - sc->txBdBase = M360AllocateBufferDescriptors(sc->txBdCount); - m360.scc1p.rbase = (char *)sc->rxBdBase - (char *)&m360; - m360.scc1p.tbase = (char *)sc->txBdBase - (char *)&m360; - - /* - * Send "Init parameters" command - */ - M360ExecuteRISC (M360_CR_OP_INIT_RX_TX | M360_CR_CHAN_SCC1); - - /* - * Set receive and transmit function codes - */ - m360.scc1p.rfcr = M360_RFCR_MOT | M360_RFCR_DMA_SPACE; - m360.scc1p.tfcr = M360_TFCR_MOT | M360_TFCR_DMA_SPACE; - - /* - * Set maximum receive buffer length - */ - m360.scc1p.mrblr = RBUF_SIZE; - - /* - * Set CRC parameters - */ - m360.scc1p.un.ethernet.c_pres = 0xFFFFFFFF; - m360.scc1p.un.ethernet.c_mask = 0xDEBB20E3; - - /* - * Clear diagnostic counters - */ - m360.scc1p.un.ethernet.crcec = 0; - m360.scc1p.un.ethernet.alec = 0; - m360.scc1p.un.ethernet.disfc = 0; - - /* - * Set pad value - */ - m360.scc1p.un.ethernet.pads = 0x8888; - - /* - * Set retry limit - */ - m360.scc1p.un.ethernet.ret_lim = 15; - - /* - * Set maximum and minimum frame length - */ - m360.scc1p.un.ethernet.mflr = 1518; - m360.scc1p.un.ethernet.minflr = 64; - m360.scc1p.un.ethernet.maxd1 = RBUF_SIZE; - m360.scc1p.un.ethernet.maxd2 = RBUF_SIZE; - - /* - * Clear group address hash table - */ - m360.scc1p.un.ethernet.gaddr1 = 0; - m360.scc1p.un.ethernet.gaddr2 = 0; - m360.scc1p.un.ethernet.gaddr3 = 0; - m360.scc1p.un.ethernet.gaddr4 = 0; - - /* - * Set our physical address - */ - hwaddr = sc->arpcom.ac_enaddr; - m360.scc1p.un.ethernet.paddr_h = (hwaddr[5] << 8) | hwaddr[4]; - m360.scc1p.un.ethernet.paddr_m = (hwaddr[3] << 8) | hwaddr[2]; - m360.scc1p.un.ethernet.paddr_l = (hwaddr[1] << 8) | hwaddr[0]; - - /* - * Aggressive retry - */ - m360.scc1p.un.ethernet.p_per = 0; - - /* - * Clear individual address hash table - */ - m360.scc1p.un.ethernet.iaddr1 = 0; - m360.scc1p.un.ethernet.iaddr2 = 0; - m360.scc1p.un.ethernet.iaddr3 = 0; - m360.scc1p.un.ethernet.iaddr4 = 0; - - /* - * Set up receive buffer descriptors - */ - for (i = 0 ; i < sc->rxBdCount ; i++) - (sc->rxBdBase + i)->status = 0; - - /* - * Set up transmit buffer descriptors - */ - for (i = 0 ; i < sc->txBdCount ; i++) { - (sc->txBdBase + i)->status = 0; - sc->txMbuf[i] = NULL; - } - sc->txBdHead = sc->txBdTail = 0; - sc->txBdActiveCount = 0; - - /* - * Clear any outstanding events - */ - m360.scc1.scce = 0xFFFF; - - /* - * Set up interrupts - */ - status = rtems_interrupt_catch (m360Enet_interrupt_handler, - (m360.cicr & 0xE0) | 0x1E, - &old_handler); - if (status != RTEMS_SUCCESSFUL) - rtems_panic ("Can't attach M360 SCC1 interrupt handler: %s\n", - rtems_status_text (status)); - m360.scc1.sccm = 0; /* No interrupts unmasked till necessary */ - m360.cimr |= (1UL << 30); /* Enable SCC1 interrupt */ - - /* - * Set up General SCC Mode Register - * Ethernet configuration - */ - m360.scc1.gsmr_h = 0x0; - m360.scc1.gsmr_l = 0x1088000c; - - /* - * Set up data synchronization register - * Ethernet synchronization pattern - */ - m360.scc1.dsr = 0xd555; - - /* - * Set up protocol-specific mode register - * Heartbeat check - * No force collision - * Discard short frames - * Individual address mode - * Ethernet CRC - * Not promisuous - * Ignore/accept broadcast packets as specified - * Normal backoff timer - * No loopback - * No input sample at end of frame - * 64-byte limit for late collision - * Wait 22 bits before looking for start of frame delimiter - * Disable full-duplex operation - */ - m360.scc1.psmr = 0x880A | (sc->acceptBroadcast ? 0 : 0x100); - - /* - * Enable the TENA (RTS1*) pin - */ -#if (defined (M68360_ATLAS_HSB)) - m360.pbpar |= 0x1000; - m360.pbdir |= 0x1000; -#else - m360.pcpar |= 0x1; - m360.pcdir &= ~0x1; -#endif -} - -/* - * Soak up buffer descriptors that have been sent - * Note that a buffer descriptor can't be retired as soon as it becomes - * ready. The MC68360 Errata (May 96) says that, "If an Ethernet frame is - * made up of multiple buffers, the user should not reuse the first buffer - * descriptor until the last buffer descriptor of the frame has had its - * ready bit cleared by the CPM". - */ -static void -m360Enet_retire_tx_bd (struct scc_softc *sc) -{ - uint16_t status; - int i; - int nRetired; - struct mbuf *m, *n; - int retries = 0; - int saveStatus = 0; - - i = sc->txBdTail; - nRetired = 0; - while ((sc->txBdActiveCount != 0) - && (((status = (sc->txBdBase + i)->status) & M360_BD_READY) == 0)) { - /* - * Check for errors which stop the transmitter. - */ - if (status & (M360_BD_LATE_COLLISION | - M360_BD_RETRY_LIMIT | - M360_BD_UNDERRUN)) { - int j; - - if (status & M360_BD_LATE_COLLISION) - sc->txLateCollision++; - if (status & M360_BD_RETRY_LIMIT) - sc->txRetryLimit++; - if (status & M360_BD_UNDERRUN) - sc->txUnderrun++; - - /* - * Reenable buffer descriptors - */ - j = sc->txBdTail; - for (;;) { - status = (sc->txBdBase + j)->status; - if (status & M360_BD_READY) - break; - (sc->txBdBase + j)->status = M360_BD_READY | - (status & (M360_BD_PAD | - M360_BD_WRAP | - M360_BD_INTERRUPT | - M360_BD_LAST | - M360_BD_TX_CRC)); - if (status & M360_BD_LAST) - break; - if (++j == sc->txBdCount) - j = 0; - } - - /* - * Move transmitter back to the first - * buffer descriptor in the frame. - */ - m360.scc1p._tbptr = m360.scc1p.tbase + - sc->txBdTail * sizeof (m360BufferDescriptor_t); - - /* - * Restart the transmitter - */ - M360ExecuteRISC (M360_CR_OP_RESTART_TX | M360_CR_CHAN_SCC1); - continue; - } - saveStatus |= status; - retries += (status >> 2) & 0xF; - nRetired++; - if (status & M360_BD_LAST) { - /* - * A full frame has been transmitted. - * Free all the associated buffer descriptors. - */ - if (saveStatus & M360_BD_DEFER) - sc->txDeferred++; - if (saveStatus & M360_BD_HEARTBEAT) - sc->txHeartbeat++; - if (saveStatus & M360_BD_CARRIER_LOST) - sc->txLostCarrier++; - saveStatus = 0; - sc->txRetry += retries; - retries = 0; - sc->txBdActiveCount -= nRetired; - while (nRetired) { - nRetired--; - m = sc->txMbuf[sc->txBdTail]; - MFREE (m, n); - if (++sc->txBdTail == sc->txBdCount) - sc->txBdTail = 0; - } - } - if (++i == sc->txBdCount) - i = 0; - } -} - -/* - * SCC reader task - */ -static void -scc_rxDaemon (void *arg) -{ - struct scc_softc *sc = (struct scc_softc *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - uint16_t status; - volatile m360BufferDescriptor_t *rxBd; - int rxBdIndex; - - /* - * Allocate space for incoming packets and start reception - */ - for (rxBdIndex = 0 ; ;) { - rxBd = sc->rxBdBase + rxBdIndex; - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod (m, void *); - if (++rxBdIndex == sc->rxBdCount) { - rxBd->status = M360_BD_EMPTY | M360_BD_INTERRUPT | M360_BD_WRAP; - break; - } - rxBd->status = M360_BD_EMPTY | M360_BD_INTERRUPT; - } - - /* - * Input packet handling loop - */ - rxBdIndex = 0; - for (;;) { - rxBd = sc->rxBdBase + rxBdIndex; - - /* - * Wait for packet if there's not one ready - */ - if ((status = rxBd->status) & M360_BD_EMPTY) { - /* - * Clear old events - */ - m360.scc1.scce = 0x8; - - /* - * Wait for packet - * Note that the buffer descriptor is checked - * *before* the event wait -- this catches the - * possibility that a packet arrived between the - * `if' above, and the clearing of the event register. - */ - while ((status = rxBd->status) & M360_BD_EMPTY) { - rtems_interrupt_level level; - rtems_event_set events; - - /* - * Unmask RXF (Full frame received) event - */ - rtems_interrupt_disable (level); - m360.scc1.sccm |= 0x8; - rtems_interrupt_enable (level); - - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - } - } - - /* - * Check that packet is valid - */ - if ((status & (M360_BD_LAST | - M360_BD_FIRST_IN_FRAME | - M360_BD_LONG | - M360_BD_NONALIGNED | - M360_BD_SHORT | - M360_BD_CRC_ERROR | - M360_BD_OVERRUN | - M360_BD_COLLISION)) == - (M360_BD_LAST | - M360_BD_FIRST_IN_FRAME)) { - /* - * Pass the packet up the chain. - * FIXME: Packet filtering hook could be done here. - */ - struct ether_header *eh; - - m = sc->rxMbuf[rxBdIndex]; - m->m_len = m->m_pkthdr.len = rxBd->length - - sizeof(uint32_t) - - sizeof(struct ether_header); - eh = mtod (m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - ether_input (ifp, eh, m); - - /* - * Allocate a new mbuf - */ - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod (m, void *); - } - else { - /* - * Something went wrong with the reception - */ - if (!(status & M360_BD_LAST)) - sc->rxNotLast++; - if (!(status & M360_BD_FIRST_IN_FRAME)) - sc->rxNotFirst++; - if (status & M360_BD_LONG) - sc->rxGiant++; - if (status & M360_BD_NONALIGNED) - sc->rxNonOctet++; - if (status & M360_BD_SHORT) - sc->rxRunt++; - if (status & M360_BD_CRC_ERROR) - sc->rxBadCRC++; - if (status & M360_BD_OVERRUN) - sc->rxOverrun++; - if (status & M360_BD_COLLISION) - sc->rxCollision++; - } - - /* - * Reenable the buffer descriptor - */ - rxBd->status = (status & (M360_BD_WRAP | M360_BD_INTERRUPT)) | M360_BD_EMPTY; - - /* - * Move to next buffer descriptor - */ - if (++rxBdIndex == sc->rxBdCount) - rxBdIndex = 0; - } -} - -static void -sendpacket (struct ifnet *ifp, struct mbuf *m) -{ - struct scc_softc *sc = ifp->if_softc; - volatile m360BufferDescriptor_t *firstTxBd, *txBd; - struct mbuf *l = NULL; - uint16_t status; - int nAdded; - - /* - * Free up buffer descriptors - */ - m360Enet_retire_tx_bd (sc); - - /* - * Set up the transmit buffer descriptors. - * No need to pad out short packets since the - * hardware takes care of that automatically. - * No need to copy the packet to a contiguous buffer - * since the hardware is capable of scatter/gather DMA. - */ - status = 0; - nAdded = 0; - txBd = firstTxBd = sc->txBdBase + sc->txBdHead; - while (m) { - /* - * There are more mbufs in the packet than there - * are transmit buffer descriptors. - * Coalesce into a single buffer. - */ - if (nAdded == sc->txBdCount) { - struct mbuf *nm; - int j; - char *dest; - - /* - * Get the pointer to the first mbuf of the packet - */ - if (sc->txBdTail != sc->txBdHead) - rtems_panic ("sendpacket coalesce"); - m = sc->txMbuf[sc->txBdTail]; - - /* - * Rescind the buffer descriptor READY bits - */ - for (j = 0 ; j < sc->txBdCount ; j++) - (sc->txBdBase + j)->status = 0; - - /* - * Allocate an mbuf cluster - * Toss the packet if allocation fails - */ - MGETHDR (nm, M_DONTWAIT, MT_DATA); - if (nm == NULL) { - sc->txCoalesceFailed++; - m_freem (m); - return; - } - MCLGET (nm, M_DONTWAIT); - if (nm->m_ext.ext_buf == NULL) { - sc->txCoalesceFailed++; - m_freem (m); - m_free (nm); - return; - } - nm->m_pkthdr = m->m_pkthdr; - nm->m_len = nm->m_pkthdr.len; - - /* - * Copy data from packet chain to mbuf cluster - */ - sc->txCoalesced++; - dest = nm->m_ext.ext_buf; - while (m) { - struct mbuf *n; - - if (m->m_len) { - memcpy (dest, mtod(m, caddr_t), m->m_len); - dest += m->m_len; - } - MFREE (m, n); - m = n; - } - - /* - * Redo the send with the new mbuf cluster - */ - m = nm; - nAdded = 0; - status = 0; - continue; - } - - /* - * Wait for buffer descriptor to become available. - */ - if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - /* - * Clear old events - */ - m360.scc1.scce = 0x12; - - /* - * Wait for buffer descriptor to become available. - * Note that the buffer descriptors are checked - * *before* entering the wait loop -- this catches - * the possibility that a buffer descriptor became - * available between the `if' above, and the clearing - * of the event register. - * This is to catch the case where the transmitter - * stops in the middle of a frame -- and only the - * last buffer descriptor in a frame can generate - * an interrupt. - */ - m360Enet_retire_tx_bd (sc); - while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - rtems_interrupt_level level; - rtems_event_set events; - - /* - * Unmask TXB (buffer transmitted) and - * TXE (transmitter error) events. - */ - rtems_interrupt_disable (level); - m360.scc1.sccm |= 0x12; - rtems_interrupt_enable (level); - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - m360Enet_retire_tx_bd (sc); - } - } - - /* - * The IP fragmentation routine in ip_output - * can produce packet fragments with zero length. - */ - if (m->m_len) { - /* - * Fill in the buffer descriptor. - * Don't set the READY flag in the first buffer - * descriptor till the whole packet has been readied. - */ - txBd = sc->txBdBase + sc->txBdHead; - txBd->buffer = mtod (m, void *); - txBd->length = m->m_len; - sc->txMbuf[sc->txBdHead] = m; - status = nAdded ? M360_BD_READY : 0; - if (++sc->txBdHead == sc->txBdCount) { - status |= M360_BD_WRAP; - sc->txBdHead = 0; - } - txBd->status = status; - l = m; - m = m->m_next; - nAdded++; - } - else { - /* - * Just toss empty mbufs - */ - struct mbuf *n; - MFREE (m, n); - m = n; - if (l != NULL) - l->m_next = m; - } - } - if (nAdded) { - /* - * Send the packet - */ - txBd->status = status | M360_BD_PAD | M360_BD_LAST | M360_BD_TX_CRC | M360_BD_INTERRUPT; - firstTxBd->status |= M360_BD_READY; - sc->txBdActiveCount += nAdded; - } -} - -/* - * Driver transmit daemon - */ -void -scc_txDaemon (void *arg) -{ - struct scc_softc *sc = (struct scc_softc *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - rtems_event_set events; - - for (;;) { - /* - * Wait for packet - */ - rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events); - - /* - * Send packets till queue is empty - */ - for (;;) { - /* - * Get the next mbuf chain to transmit. - */ - IF_DEQUEUE(&ifp->if_snd, m); - if (!m) - break; - sendpacket (ifp, m); - } - ifp->if_flags &= ~IFF_OACTIVE; - } -} - -/* - * Send packet (caller provides header). - */ -static void -scc_start (struct ifnet *ifp) -{ - struct scc_softc *sc = ifp->if_softc; - - rtems_bsdnet_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); - ifp->if_flags |= IFF_OACTIVE; -} - -/* - * Initialize and start the device - */ -static void -scc_init (void *arg) -{ - struct scc_softc *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - - if (sc->txDaemonTid == 0) { - - /* - * Set up SCC hardware - */ - m360Enet_initialize_hardware (sc); - - /* - * Start driver tasks - */ - sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, scc_txDaemon, sc); - sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, scc_rxDaemon, sc); - - } - - /* - * Set flags appropriately - */ - if (ifp->if_flags & IFF_PROMISC) - m360.scc1.psmr |= 0x200; - else - m360.scc1.psmr &= ~0x200; - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - - /* - * Enable receiver and transmitter - */ - m360.scc1.gsmr_l |= 0x30; -} - -/* - * Stop the device - */ -static void -scc_stop (struct scc_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - /* - * Shut down receiver and transmitter - */ - m360.scc1.gsmr_l &= ~0x30; -} - -/* - * Show interface statistics - */ -static void -scc_stats (struct scc_softc *sc) -{ - printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); - printf (" Not First:%-8lu", sc->rxNotFirst); - printf (" Not Last:%-8lu\n", sc->rxNotLast); - printf (" Giant:%-8lu", sc->rxGiant); - printf (" Runt:%-8lu", sc->rxRunt); - printf (" Non-octet:%-8lu\n", sc->rxNonOctet); - printf (" Bad CRC:%-8lu", sc->rxBadCRC); - printf (" Overrun:%-8lu", sc->rxOverrun); - printf (" Collision:%-8lu\n", sc->rxCollision); - printf (" Discarded:%-8lu\n", (unsigned long)m360.scc1p.un.ethernet.disfc); - - printf (" Tx Interrupts:%-8lu", sc->txInterrupts); - printf (" Deferred:%-8lu", sc->txDeferred); - printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat); - printf (" No Carrier:%-8lu", sc->txLostCarrier); - printf ("Retransmit Limit:%-8lu", sc->txRetryLimit); - printf (" Late Collision:%-8lu\n", sc->txLateCollision); - printf (" Underrun:%-8lu", sc->txUnderrun); - printf (" Raw output wait:%-8lu", sc->txRawWait); - printf (" Coalesced:%-8lu\n", sc->txCoalesced); - printf (" Coalesce failed:%-8lu", sc->txCoalesceFailed); - printf (" Retries:%-8lu\n", sc->txRetry); -} - -/* - * Driver ioctl handler - */ -static int -scc_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct scc_softc *sc = ifp->if_softc; - int error = 0; - - switch (command) { - case SIOCGIFADDR: - case SIOCSIFADDR: - ether_ioctl (ifp, command, data); - break; - - case SIOCSIFFLAGS: - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { - case IFF_RUNNING: - scc_stop (sc); - break; - - case IFF_UP: - scc_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - scc_stop (sc); - scc_init (sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - scc_stats (sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - return error; -} - -/* - * Attach an SCC driver to the system - */ -int -rtems_scc1_driver_attach (struct rtems_bsdnet_ifconfig *config, int attaching) -{ - struct scc_softc *sc; - struct ifnet *ifp; - int mtu; - int unitNumber; - char *unitName; - - /* - * Make sure we're really being attached - */ - if (!attaching) { - printf ("SCC1 driver can not be detached.\n"); - return 0; - } - - /* - * Parse driver name - */ - if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0) - return 0; - - /* - * Is driver free? - */ - if ((unitNumber <= 0) || (unitNumber > NSCCDRIVER)) { - printf ("Bad SCC unit number.\n"); - return 0; - } - sc = &scc_softc[unitNumber - 1]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc != NULL) { - printf ("Driver already in use.\n"); - return 0; - } - - /* - * Process options - */ - if (config->hardware_address) { - memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - } - else { - /* - * The first 4 bytes of the bootstrap prom - * contain the value loaded into the stack - * pointer as part of the CPU32's hardware - * reset exception handler. The following - * 4 bytes contain the value loaded into the - * program counter. The boards' Ethernet - * address is stored in the six bytes - * immediately preceding this initial - * program counter value. - * - * See start360/start360.s. - */ - const unsigned long *ExceptionVectors; - const unsigned char *entryPoint; - - /* - * Sanity check -- assume entry point must be - * within 1 MByte of beginning of boot ROM. - */ - ExceptionVectors = (const unsigned long *)&_RomBase; - entryPoint = (const unsigned char *)ExceptionVectors[1]; - if (((unsigned long)entryPoint - (unsigned long)ExceptionVectors) - >= (1 * 1024 * 1024)) { - printf ("Warning -- Ethernet address can not be found in bootstrap PROM.\n"); - sc->arpcom.ac_enaddr[0] = 0x08; - sc->arpcom.ac_enaddr[1] = 0xF3; - sc->arpcom.ac_enaddr[2] = 0x3E; - sc->arpcom.ac_enaddr[3] = 0xC2; - sc->arpcom.ac_enaddr[4] = 0x7E; - sc->arpcom.ac_enaddr[5] = 0x38; - } - else { - memcpy (sc->arpcom.ac_enaddr, entryPoint - ETHER_ADDR_LEN, ETHER_ADDR_LEN); - } - } - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - if (config->rbuf_count) - sc->rxBdCount = config->rbuf_count; - else - sc->rxBdCount = RX_BUF_COUNT; - if (config->xbuf_count) - sc->txBdCount = config->xbuf_count; - else - sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; - sc->acceptBroadcast = !config->ignore_broadcast; - - /* - * Set up network interface values - */ - ifp->if_softc = sc; - ifp->if_unit = unitNumber; - ifp->if_name = unitName; - ifp->if_mtu = mtu; - ifp->if_init = scc_init; - ifp->if_ioctl = scc_ioctl; - ifp->if_start = scc_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - /* - * Attach the interface - */ - if_attach (ifp); - ether_ifattach (ifp); - return 1; -} -- cgit v1.2.3