aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/ed/if_ed.c
diff options
context:
space:
mode:
authorDavid Greenman <dg@FreeBSD.org>1993-11-22 11:08:16 +0000
committerDavid Greenman <dg@FreeBSD.org>1993-11-22 11:08:16 +0000
commit047ea5bd0ce2b9ffa31e1fa3d70bd7e59efb7ee5 (patch)
treeb3f71b55a7eccb78686e14be6c9ab9b6239af389 /sys/dev/ed/if_ed.c
parentb513c26294324c9c81aa94c85d2e8dc2d3ffd009 (diff)
downloadsrc-047ea5bd0ce2b9ffa31e1fa3d70bd7e59efb7ee5.tar.gz
src-047ea5bd0ce2b9ffa31e1fa3d70bd7e59efb7ee5.zip
* Revision 2.14 1993/11/22 10:55:30 davidg
* change all splnet's to splimp's * * Revision 2.13 1993/11/22 10:53:52 davidg * patch to add support for SMC8216 (Elite-Ultra) boards * from Glen H. Lowe * * Revision 2.12 1993/11/07 18:04:13 davidg * fix from Garrett Wollman: * add a return(0) at the end of ed_probe so that if the various device * specific probes fail that we just don't fall of the end of the function.
Notes
Notes: svn path=/head/; revision=791
Diffstat (limited to 'sys/dev/ed/if_ed.c')
-rw-r--r--sys/dev/ed/if_ed.c176
1 files changed, 140 insertions, 36 deletions
diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c
index 5cbf73c9eb24..600f61159845 100644
--- a/sys/dev/ed/if_ed.c
+++ b/sys/dev/ed/if_ed.c
@@ -20,12 +20,24 @@
*/
/*
- * $Id: if_ed.c,v 1.21 1993/10/23 04:52:41 davidg Exp $
+ * $Id: if_ed.c,v 2.14 1993/11/22 10:55:30 davidg Exp davidg $
*/
/*
* Modification history
*
+ * Revision 2.14 1993/11/22 10:55:30 davidg
+ * change all splnet's to splimp's
+ *
+ * Revision 2.13 1993/11/22 10:53:52 davidg
+ * patch to add support for SMC8216 (Elite-Ultra) boards
+ * from Glen H. Lowe
+ *
+ * Revision 2.12 1993/11/07 18:04:13 davidg
+ * fix from Garrett Wollman:
+ * add a return(0) at the end of ed_probe so that if the various device
+ * specific probes fail that we just don't fall of the end of the function.
+ *
* Revision 2.11 1993/10/23 04:21:03 davidg
* Novell probe changed to be invasive because of too many complaints
* about some clone boards not being reset properly and thus not
@@ -151,6 +163,7 @@ struct ed_softc {
*/
u_char wd_laar_proto;
u_char isa16bit; /* width of access to card 0=8 or 1=16 */
+ int is790; /* set by the probe code if the card is 790 based */
caddr_t bpf; /* BPF "magic cookie" */
caddr_t mem_start; /* NIC memory start address */
@@ -211,6 +224,19 @@ static unsigned short ed_intr_mask[] = {
IRQ4
};
+/*
+ * Interrupt conversion table for 585/790 Combo
+ */
+static unsigned short ed_790_intr_mask[] = {
+ 0,
+ IRQ9,
+ IRQ3,
+ IRQ4,
+ IRQ5,
+ IRQ10,
+ IRQ11,
+ IRQ15
+};
#define ETHER_MIN_LEN 64
#define ETHER_MAX_LEN 1518
#define ETHER_ADDR_LEN 6
@@ -241,7 +267,7 @@ ed_probe(isa_dev)
if (nports = ed_probe_Novell(isa_dev))
return (nports);
- return 0; /* Added by GW: don't fall off the end */
+ return(0);
}
/*
@@ -295,6 +321,7 @@ ed_probe_WD80x3(isa_dev)
sc->asic_addr = isa_dev->id_iobase;
sc->nic_addr = sc->asic_addr + ED_WD_NIC_OFFSET;
+ sc->is790 = 0;
/*
* Attempt to do a checksum over the station address PROM.
@@ -372,6 +399,18 @@ ed_probe_WD80x3(isa_dev)
memsize = 16384;
isa16bit = 1;
break;
+ case ED_TYPE_SMC8216C:
+ sc->type_str = "SMC8216/SMC8216C";
+ memsize = 16384;
+ isa16bit = 1;
+ sc->is790 = 1;
+ break;
+ case ED_TYPE_SMC8216T:
+ sc->type_str = "SMC8216T";
+ memsize = 16384;
+ isa16bit = 1;
+ sc->is790 = 1;
+ break;
default:
sc->type_str = "";
memsize = 8192;
@@ -413,7 +452,7 @@ ed_probe_WD80x3(isa_dev)
* 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) {
+ if ((sc->type & ED_WD_SOFTCONFIG) && (!sc->is790)) {
/*
* Assemble together the encoded interrupt number.
*/
@@ -434,6 +473,19 @@ ed_probe_WD80x3(isa_dev)
outb(isa_dev->id_iobase + ED_WD_IRR,
inb(isa_dev->id_iobase + ED_WD_IRR) | ED_WD_IRR_IEN);
}
+ if (sc->is790) {
+ outb(isa_dev->id_iobase + 0x04, inb(isa_dev->id_iobase + 0x04) | 0x80);
+ iptr = ((inb(isa_dev->id_iobase + 0x0d) & 0x0c ) >> 2) |
+ ((inb(isa_dev->id_iobase + 0x0d) & 0x40) >> 4);
+ outb(isa_dev->id_iobase + 0x04, inb(isa_dev->id_iobase + 0x04) & ~0x80);
+
+ if (ed_790_intr_mask[iptr] != isa_dev->id_irq) {
+ printf("ed%d: kernel configured irq %d doesn't match board configured irq %d %d\n",
+ isa_dev->id_unit, ffs(isa_dev->id_irq) - 1, ffs(ed_790_intr_mask[iptr]) -1, iptr);
+ return 0;
+ }
+ outb(isa_dev->id_iobase + 0x06, inb(isa_dev->id_iobase + 0x06) | 0x01);
+ }
sc->isa16bit = isa16bit;
@@ -483,20 +535,34 @@ ed_probe_WD80x3(isa_dev)
/*
* Set address and enable interface shared memory.
*/
- outb(sc->asic_addr + ED_WD_MSR, ((kvtop(sc->mem_start) >> 13) &
- ED_WD_MSR_ADDR) | ED_WD_MSR_MENB);
+ if(!sc->is790) {
+ outb(sc->asic_addr + ED_WD_MSR, ((kvtop(sc->mem_start) >> 13) &
+ ED_WD_MSR_ADDR) | ED_WD_MSR_MENB);
+ } else {
+ outb(sc->asic_addr + ED_WD_MSR, ED_WD_MSR_MENB);
+ outb(sc->asic_addr + 0x04, (inb(sc->asic_addr + 0x04) | 0x80));
+ outb(sc->asic_addr + 0x0b, ((kvtop(sc->mem_start) >> 13) & 0x0f) |
+ ((kvtop(sc->mem_start) >> 11) & 0x40) |
+ (inb(sc->asic_addr + 0x0b) & 0xb0));
+ outb(sc->asic_addr + 0x04, (inb(sc->asic_addr + 0x04) & ~0x80));
+ }
/*
* Set upper address bits and 8/16 bit access to shared memory
*/
if (isa16bit) {
- outb(sc->asic_addr + ED_WD_LAAR, (sc->wd_laar_proto =
- ED_WD_LAAR_L16EN | ED_WD_LAAR_M16EN |
- ((kvtop(sc->mem_start) >> 19) & ED_WD_LAAR_ADDRHI)));
+ if (sc->is790) {
+ sc->wd_laar_proto = inb(sc->asic_addr + ED_WD_LAAR);
+ outb(sc->asic_addr + ED_WD_LAAR, ED_WD_LAAR_M16EN);
+ } else {
+ outb(sc->asic_addr + ED_WD_LAAR, (sc->wd_laar_proto =
+ ED_WD_LAAR_L16EN | ED_WD_LAAR_M16EN |
+ ((kvtop(sc->mem_start) >> 19) & ED_WD_LAAR_ADDRHI)));
+ }
} else {
- if ((sc->type & ED_WD_SOFTCONFIG) || (sc->type == ED_TYPE_WD8013EBT)) {
+ if ((sc->type & ED_WD_SOFTCONFIG) || (sc->type == ED_TYPE_WD8013EBT) && (!sc->is790)) {
outb(sc->asic_addr + ED_WD_LAAR, (sc->wd_laar_proto =
- ((kvtop(sc->mem_start) >> 19) & ED_WD_LAAR_ADDRHI)));
+ ((kvtop(sc->mem_start) >> 19) & ED_WD_LAAR_ADDRHI)));
}
}
@@ -1059,7 +1125,7 @@ ed_reset(unit)
{
int s;
- s = splnet();
+ s = splimp();
/*
* Stop interface and re-initialize.
@@ -1083,8 +1149,11 @@ ed_stop(unit)
/*
* Stop everything on the interface, and select page 0 registers.
*/
- outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STP);
-
+ if (sc->is790) {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_STP);
+ } else {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STP);
+ }
/*
* Wait for interface to enter stopped state, but limit # of checks
* to 'n' (about 5ms). It shouldn't even take 5us on modern
@@ -1130,7 +1199,7 @@ ed_init(unit)
* This init procedure is "mandatory"...don't change what or when
* things happen.
*/
- s = splnet();
+ s = splimp();
/* reset transmitter flags */
sc->xmit_busy = 0;
@@ -1146,8 +1215,11 @@ ed_init(unit)
/*
* Set interface for page 0, Remote DMA complete, Stopped
*/
- outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STP);
-
+ if (sc->is790) {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_STP);
+ } else {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STP);
+ }
if (sc->isa16bit) {
/*
* Set FIFO threshold to 8, No auto-init Remote DMA,
@@ -1182,6 +1254,9 @@ ed_init(unit)
*/
outb(sc->nic_addr + ED_P0_TPSR, sc->tx_page_start);
outb(sc->nic_addr + ED_P0_PSTART, sc->rec_page_start);
+ /* Set lower bits of byte addressable framing to 0 */
+ if (sc->is790)
+ outb(sc->nic_addr + 0x09, 0);
/*
* Initialize Receiver (ring-buffer) Page Stop and Boundry
@@ -1207,8 +1282,11 @@ ed_init(unit)
/*
* Program Command Register for page 1
*/
- outb(sc->nic_addr + ED_P0_CR, ED_CR_PAGE_1|ED_CR_RD2|ED_CR_STP);
-
+ if (sc->is790) {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_PAGE_1|ED_CR_STP);
+ } else {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_PAGE_1|ED_CR_RD2|ED_CR_STP);
+ }
/*
* Copy out our station address
*/
@@ -1233,8 +1311,11 @@ ed_init(unit)
* Set Command Register for page 0, Remote DMA complete,
* and interface Start.
*/
- outb(sc->nic_addr + ED_P1_CR, ED_CR_RD2|ED_CR_STA);
-
+ if (sc->is790) {
+ outb(sc->nic_addr + ED_P1_CR, ED_CR_STA);
+ } else {
+ outb(sc->nic_addr + ED_P1_CR, ED_CR_RD2|ED_CR_STA);
+ }
/*
* Take interface out of loopback
*/
@@ -1280,8 +1361,11 @@ static inline void ed_xmit(ifp)
/*
* Set NIC for page 0 register access
*/
- outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STA);
-
+ if (sc->is790) {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_STA);
+ } else {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STA);
+ }
/*
* Set TX buffer start page
*/
@@ -1297,8 +1381,11 @@ static inline void ed_xmit(ifp)
/*
* 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);
-
+ if (sc->is790) {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_TXP | ED_CR_STA);
+ } else {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_TXP|ED_CR_STA);
+ }
sc->xmit_busy = 1;
/*
@@ -1317,7 +1404,7 @@ static inline void ed_xmit(ifp)
/*
* Start output on interface.
* We make two assumptions here:
- * 1) that the current priority is set to splnet _before_ this code
+ * 1) that the current priority is set to splimp _before_ this code
* is called *and* is returned to the appropriate priority after
* return
* 2) that the IFF_OACTIVE flag is checked before this code is called
@@ -1534,8 +1621,11 @@ ed_rint(unit)
/*
* Set NIC to page 1 registers to get 'current' pointer
*/
- outb(sc->nic_addr + ED_P0_CR, ED_CR_PAGE_1|ED_CR_RD2|ED_CR_STA);
-
+ if (sc->is790) {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_PAGE_1|ED_CR_STA);
+ } else {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_PAGE_1|ED_CR_RD2|ED_CR_STA);
+ }
/*
* 'sc->next_packet' is the logical beginning of the ring-buffer - i.e.
* it points to where new data has been buffered. The 'CURR'
@@ -1596,15 +1686,22 @@ ed_rint(unit)
/*
* Set NIC to page 0 registers to update boundry register
*/
- outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STA);
-
+ if (sc->is790) {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_STA);
+ } else {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STA);
+ }
outb(sc->nic_addr + ED_P0_BNRY, boundry);
/*
* Set NIC to page 1 registers before looping to top (prepare to
* get 'CURR' current pointer)
*/
- outb(sc->nic_addr + ED_P0_CR, ED_CR_PAGE_1|ED_CR_RD2|ED_CR_STA);
+ if (sc->is790) {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_PAGE_1|ED_CR_STA);
+ } else {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_PAGE_1|ED_CR_RD2|ED_CR_STA);
+ }
}
}
@@ -1621,8 +1718,11 @@ edintr(unit)
/*
* Set NIC to page 0 registers
*/
- outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STA);
-
+ if (sc->is790) {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_STA);
+ } else {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STA);
+ }
/*
* loop until there are no more new interrupts
*/
@@ -1641,7 +1741,7 @@ edintr(unit)
* some conditions.
*/
if (isr & (ED_ISR_PTX|ED_ISR_TXE)) {
- u_char collisions = inb(sc->nic_addr + ED_P0_NCR);
+ u_char collisions = inb(sc->nic_addr + ED_P0_NCR) & 0x0f;
/*
* Check for transmit error. If a TX completed with an
@@ -1652,6 +1752,7 @@ edintr(unit)
* course, with UDP we're screwed, but this is expected
* when a network is heavily loaded.
*/
+ (void) inb(sc->nic_addr + ED_P0_TSR);
if (isr & ED_ISR_TXE) {
/*
@@ -1793,8 +1894,11 @@ edintr(unit)
* in the transmit routine, is *okay* - it is 'edge'
* triggered from low to high)
*/
- outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STA);
-
+ if (sc->is790) {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_STA);
+ } else {
+ outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STA);
+ }
/*
* If the Network Talley Counters overflow, read them to
* reset them. It appears that old 8390's won't
@@ -1824,7 +1928,7 @@ ed_ioctl(ifp, command, data)
struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
- s = splnet();
+ s = splimp();
switch (command) {