diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c index ec1d6825e2f7..697e4d0dd618 100644 --- a/sys/dev/ed/if_ed.c +++ b/sys/dev/ed/if_ed.c @@ -17,6 +17,13 @@ * Modification history * * $Log: if_ed.c,v $ + * Revision 1.9 93/06/23 03:48:14 davidg + * fixed minor typo introduced when cleaning up probe routine + * + * Revision 1.8 93/06/23 03:37:19 davidg + * cleaned up/added some comments. Also improved readability of a part of + * the probe routine. + * * Revision 1.7 93/06/22 04:45:01 davidg * (no additional changes) Second beta release * @@ -286,16 +293,31 @@ type_WD80x3: for (i=0; i<8; i++) printf("%x -> %x\n", i, inb(sc->asic_addr + i)); #endif - + /* + * Check 83C584 interrupt configuration register if this board has one + * XXX - we could also check the IO address register. But why + * bother...if we get past this, it *has* to be correct. + */ if (sc->type & ED_WD_SOFTCONFIG) { - iptr = inb(isa_dev->id_iobase + 1) & 4 | - ((inb(isa_dev->id_iobase+4) & 0x60) >> 5); + /* + * Assemble together the encoded interrupt number. + */ + iptr = (inb(isa_dev->id_iobase + ED_WD_ICR) & ED_WD_ICR_IR2) | + ((inb(isa_dev->id_iobase + ED_WD_IRR) & + (ED_WD_IRR_IR0 | ED_WD_IRR_IR1)) >> 5); + /* + * Translate it using translation table, and check for correctness. + */ if (ed_intr_mask[iptr] != isa_dev->id_irq) { printf("ed%d: kernel configured irq doesn't match board configured irq\n", isa_dev->id_unit); return(0); } - outb(isa_dev->id_iobase+4, inb(isa_dev->id_iobase+4) | 0x80); + /* + * Enable the interrupt. + */ + outb(isa_dev->id_iobase + ED_WD_IRR, + inb(isa_dev->id_iobase + ED_WD_IRR) | ED_WD_IRR_IEN); } sc->memwidth = memwidth; @@ -659,6 +681,9 @@ ed_attach(isa_dev) else ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS); + /* + * Attach the interface + */ if_attach(ifp); #if NBPFILTER > 0 @@ -672,9 +697,10 @@ ed_attach(isa_dev) while ((ifa != 0) && (ifa->ifa_addr != 0) && (ifa->ifa_addr->sa_family != AF_LINK)) ifa = ifa->ifa_next; - /* - * If we find an AF_LINK type entry we fill in the hardware address + * If we find an AF_LINK type entry we fill in the hardware address. + * This is useful for netstat(1) to keep track of which interface + * is which. */ if ((ifa != 0) && (ifa->ifa_addr != 0)) { /* @@ -742,6 +768,10 @@ ed_stop(unit) } } +/* + * Device timeout/watchdog routine. Entered if the device neglects to + * generate an interrupt after a transmit has been started on it. + */ int ed_watchdog(unit) int unit; @@ -904,6 +934,9 @@ ed_init(unit) (void) splx(s); } +/* + * This routine actually starts the transmission on the interface + */ static inline void ed_xmit(ifp) struct ifnet *ifp; { @@ -928,13 +961,16 @@ static inline void ed_xmit(ifp) outb(sc->nic_addr + ED_P0_TBCR1, len >> 8); /* - * Set page 0, Remote DMA complete, Transmit Packet, and Start + * Set page 0, Remote DMA complete, Transmit Packet, and *Start* */ outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_TXP|ED_CR_STA); sc->xmit_busy = 1; sc->data_buffered = 0; + /* + * Switch buffers if we are doing double-buffered transmits + */ if ((sc->txb_next == 0) && (sc->txb_cnt > 1)) sc->txb_next = 1; else @@ -966,14 +1002,24 @@ ed_start(ifp) u_char laar_tmp; outloop: + /* + * See if there is room to send more data (i.e. one or both of the + * buffers is empty). + */ if (sc->data_buffered) if (sc->xmit_busy) { + /* + * No room. Indicate this to the outside world + * and exit. + */ ifp->if_flags |= IFF_OACTIVE; return; } else { /* + * Data is buffered, but we're not transmitting, so + * start the xmit on the buffered data. * Note that ed_xmit() resets the data_buffered flag - * before returning + * before returning. */ ed_xmit(ifp); } @@ -1104,6 +1150,10 @@ outloop: m_freem(m0); + /* + * If we are doing double-buffering, a buffer might be free to + * fill with another packet, so loop back to the top. + */ if (sc->txb_cnt > 1) goto outloop; else { @@ -1260,7 +1310,7 @@ edintr(unit) sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; /* - * reset watchdog timer + * clear watchdog timer */ sc->arpcom.ac_if.if_timer = 0; } @@ -1310,7 +1360,7 @@ edintr(unit) sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; /* - * reset watchdog timer + * clear watchdog timer */ sc->arpcom.ac_if.if_timer = 0; @@ -1698,9 +1748,15 @@ ed_ring_to_mbuf(sc,src,dst,total_len) if (amount == 0) { /* no more data in this mbuf, alloc another */ /* - * if there is enough data for an mbuf cluster, attempt - * to allocate one of those, otherwise, a regular mbuf - * will do. + * If there is enough data for an mbuf cluster, attempt + * to allocate one of those, otherwise, a regular + * mbuf will do. + * Note that a regular mbuf is always required, even if + * we get a cluster - getting a cluster does not + * allocate any mbufs, and one is needed to assign + * the cluster to. The mbuf that has a cluster + * extension can not be used to contain data - only + * the cluster can contain data. */ dst = m; MGET(m, M_DONTWAIT, MT_DATA); diff --git a/sys/dev/ed/if_edreg.h b/sys/dev/ed/if_edreg.h index a202848322d4..f44ea59f3a82 100644 --- a/sys/dev/ed/if_edreg.h +++ b/sys/dev/ed/if_edreg.h @@ -1,5 +1,14 @@ /* * National Semiconductor DS8390 NIC register definitions + * + * $Log: if_edreg.h,v $ + * Revision 1.2 93/06/23 03:03:05 davidg + * added some additional definitions for the 83C584 bus interface + * chip (SMC/WD boards) + * + * Revision 1.1 93/06/23 03:01:07 davidg + * Initial revision + * */ /* @@ -573,13 +582,23 @@ struct ed_ring { #define ED_WD_ICR_16BIT 0x01 /* 16-bit interface */ #define ED_WD_ICR_OAR 0x02 /* select register. 0=BIO 1=EAR */ -#define ED_WD_ICR_IR2 0x04 /* select second set of IRQs */ +#define ED_WD_ICR_IR2 0x04 /* high order bit of encoded IRQ */ #define ED_WD_ICR_MSZ 0x08 /* memory size (0=8k 1=32k) */ #define ED_WD_ICR_RLA 0x10 /* recall LAN address */ #define ED_WD_ICR_RX7 0x20 /* recall all but i/o and LAN address */ #define ED_WD_ICR_RIO 0x40 /* recall i/o address */ #define ED_WD_ICR_STO 0x80 /* store to non-volatile memory */ +/* + * IO Address Register (IAR) + */ +#define ED_WD_IAR 2 + +/* + * EEROM Address Register + */ +#define ED_WD_EAR 3 + /* * Interrupt Request Register (IRR) */ @@ -590,6 +609,22 @@ struct ed_ring { #define ED_WD_IRR_OUT2 0x04 /* WD83C584 pin 2 output */ #define ED_WD_IRR_OUT3 0x08 /* WD83C584 pin 3 output */ #define ED_WD_IRR_FLASH 0x10 /* Flash RAM is in the ROM socket */ + +/* + * The three bit of the encoded IRQ are decoded as follows: + * + * IR2 IR1 IR0 IRQ + * 0 0 0 2/9 + * 0 0 1 3 + * 0 1 0 5 + * 0 1 1 7 + * 1 0 0 10 + * 1 0 1 11 + * 1 1 0 15 + * 1 1 1 4 + */ +#define ED_WD_IRR_IR0 0x20 /* bit 0 of encoded IRQ */ +#define ED_WD_IRR_IR1 0x40 /* bit 1 of encoded IRQ */ #define ED_WD_IRR_IEN 0x80 /* Interrupt enable */ /* diff --git a/sys/i386/isa/if_ed.c b/sys/i386/isa/if_ed.c index ec1d6825e2f7..697e4d0dd618 100644 --- a/sys/i386/isa/if_ed.c +++ b/sys/i386/isa/if_ed.c @@ -17,6 +17,13 @@ * Modification history * * $Log: if_ed.c,v $ + * Revision 1.9 93/06/23 03:48:14 davidg + * fixed minor typo introduced when cleaning up probe routine + * + * Revision 1.8 93/06/23 03:37:19 davidg + * cleaned up/added some comments. Also improved readability of a part of + * the probe routine. + * * Revision 1.7 93/06/22 04:45:01 davidg * (no additional changes) Second beta release * @@ -286,16 +293,31 @@ type_WD80x3: for (i=0; i<8; i++) printf("%x -> %x\n", i, inb(sc->asic_addr + i)); #endif - + /* + * Check 83C584 interrupt configuration register if this board has one + * XXX - we could also check the IO address register. But why + * bother...if we get past this, it *has* to be correct. + */ if (sc->type & ED_WD_SOFTCONFIG) { - iptr = inb(isa_dev->id_iobase + 1) & 4 | - ((inb(isa_dev->id_iobase+4) & 0x60) >> 5); + /* + * Assemble together the encoded interrupt number. + */ + iptr = (inb(isa_dev->id_iobase + ED_WD_ICR) & ED_WD_ICR_IR2) | + ((inb(isa_dev->id_iobase + ED_WD_IRR) & + (ED_WD_IRR_IR0 | ED_WD_IRR_IR1)) >> 5); + /* + * Translate it using translation table, and check for correctness. + */ if (ed_intr_mask[iptr] != isa_dev->id_irq) { printf("ed%d: kernel configured irq doesn't match board configured irq\n", isa_dev->id_unit); return(0); } - outb(isa_dev->id_iobase+4, inb(isa_dev->id_iobase+4) | 0x80); + /* + * Enable the interrupt. + */ + outb(isa_dev->id_iobase + ED_WD_IRR, + inb(isa_dev->id_iobase + ED_WD_IRR) | ED_WD_IRR_IEN); } sc->memwidth = memwidth; @@ -659,6 +681,9 @@ ed_attach(isa_dev) else ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS); + /* + * Attach the interface + */ if_attach(ifp); #if NBPFILTER > 0 @@ -672,9 +697,10 @@ ed_attach(isa_dev) while ((ifa != 0) && (ifa->ifa_addr != 0) && (ifa->ifa_addr->sa_family != AF_LINK)) ifa = ifa->ifa_next; - /* - * If we find an AF_LINK type entry we fill in the hardware address + * If we find an AF_LINK type entry we fill in the hardware address. + * This is useful for netstat(1) to keep track of which interface + * is which. */ if ((ifa != 0) && (ifa->ifa_addr != 0)) { /* @@ -742,6 +768,10 @@ ed_stop(unit) } } +/* + * Device timeout/watchdog routine. Entered if the device neglects to + * generate an interrupt after a transmit has been started on it. + */ int ed_watchdog(unit) int unit; @@ -904,6 +934,9 @@ ed_init(unit) (void) splx(s); } +/* + * This routine actually starts the transmission on the interface + */ static inline void ed_xmit(ifp) struct ifnet *ifp; { @@ -928,13 +961,16 @@ static inline void ed_xmit(ifp) outb(sc->nic_addr + ED_P0_TBCR1, len >> 8); /* - * Set page 0, Remote DMA complete, Transmit Packet, and Start + * Set page 0, Remote DMA complete, Transmit Packet, and *Start* */ outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_TXP|ED_CR_STA); sc->xmit_busy = 1; sc->data_buffered = 0; + /* + * Switch buffers if we are doing double-buffered transmits + */ if ((sc->txb_next == 0) && (sc->txb_cnt > 1)) sc->txb_next = 1; else @@ -966,14 +1002,24 @@ ed_start(ifp) u_char laar_tmp; outloop: + /* + * See if there is room to send more data (i.e. one or both of the + * buffers is empty). + */ if (sc->data_buffered) if (sc->xmit_busy) { + /* + * No room. Indicate this to the outside world + * and exit. + */ ifp->if_flags |= IFF_OACTIVE; return; } else { /* + * Data is buffered, but we're not transmitting, so + * start the xmit on the buffered data. * Note that ed_xmit() resets the data_buffered flag - * before returning + * before returning. */ ed_xmit(ifp); } @@ -1104,6 +1150,10 @@ outloop: m_freem(m0); + /* + * If we are doing double-buffering, a buffer might be free to + * fill with another packet, so loop back to the top. + */ if (sc->txb_cnt > 1) goto outloop; else { @@ -1260,7 +1310,7 @@ edintr(unit) sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; /* - * reset watchdog timer + * clear watchdog timer */ sc->arpcom.ac_if.if_timer = 0; } @@ -1310,7 +1360,7 @@ edintr(unit) sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; /* - * reset watchdog timer + * clear watchdog timer */ sc->arpcom.ac_if.if_timer = 0; @@ -1698,9 +1748,15 @@ ed_ring_to_mbuf(sc,src,dst,total_len) if (amount == 0) { /* no more data in this mbuf, alloc another */ /* - * if there is enough data for an mbuf cluster, attempt - * to allocate one of those, otherwise, a regular mbuf - * will do. + * If there is enough data for an mbuf cluster, attempt + * to allocate one of those, otherwise, a regular + * mbuf will do. + * Note that a regular mbuf is always required, even if + * we get a cluster - getting a cluster does not + * allocate any mbufs, and one is needed to assign + * the cluster to. The mbuf that has a cluster + * extension can not be used to contain data - only + * the cluster can contain data. */ dst = m; MGET(m, M_DONTWAIT, MT_DATA); diff --git a/sys/i386/isa/if_edreg.h b/sys/i386/isa/if_edreg.h index a202848322d4..f44ea59f3a82 100644 --- a/sys/i386/isa/if_edreg.h +++ b/sys/i386/isa/if_edreg.h @@ -1,5 +1,14 @@ /* * National Semiconductor DS8390 NIC register definitions + * + * $Log: if_edreg.h,v $ + * Revision 1.2 93/06/23 03:03:05 davidg + * added some additional definitions for the 83C584 bus interface + * chip (SMC/WD boards) + * + * Revision 1.1 93/06/23 03:01:07 davidg + * Initial revision + * */ /* @@ -573,13 +582,23 @@ struct ed_ring { #define ED_WD_ICR_16BIT 0x01 /* 16-bit interface */ #define ED_WD_ICR_OAR 0x02 /* select register. 0=BIO 1=EAR */ -#define ED_WD_ICR_IR2 0x04 /* select second set of IRQs */ +#define ED_WD_ICR_IR2 0x04 /* high order bit of encoded IRQ */ #define ED_WD_ICR_MSZ 0x08 /* memory size (0=8k 1=32k) */ #define ED_WD_ICR_RLA 0x10 /* recall LAN address */ #define ED_WD_ICR_RX7 0x20 /* recall all but i/o and LAN address */ #define ED_WD_ICR_RIO 0x40 /* recall i/o address */ #define ED_WD_ICR_STO 0x80 /* store to non-volatile memory */ +/* + * IO Address Register (IAR) + */ +#define ED_WD_IAR 2 + +/* + * EEROM Address Register + */ +#define ED_WD_EAR 3 + /* * Interrupt Request Register (IRR) */ @@ -590,6 +609,22 @@ struct ed_ring { #define ED_WD_IRR_OUT2 0x04 /* WD83C584 pin 2 output */ #define ED_WD_IRR_OUT3 0x08 /* WD83C584 pin 3 output */ #define ED_WD_IRR_FLASH 0x10 /* Flash RAM is in the ROM socket */ + +/* + * The three bit of the encoded IRQ are decoded as follows: + * + * IR2 IR1 IR0 IRQ + * 0 0 0 2/9 + * 0 0 1 3 + * 0 1 0 5 + * 0 1 1 7 + * 1 0 0 10 + * 1 0 1 11 + * 1 1 0 15 + * 1 1 1 4 + */ +#define ED_WD_IRR_IR0 0x20 /* bit 0 of encoded IRQ */ +#define ED_WD_IRR_IR1 0x40 /* bit 1 of encoded IRQ */ #define ED_WD_IRR_IEN 0x80 /* Interrupt enable */ /*