1 /*-
2 * Copyright (c) 2003 Matthew N. Dodd
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * Portions:
27 * Copyright (c) 1992, 1993, University of Vermont and State
28 * Agricultural College.
29 * Copyright (c) 1992, 1993, Garrett A. Wollman.
30 * Copyright (c) 1990, 1991, William F. Jolitz
31 * Copyright (c) 1990, The Regents of the University of California
32 * Copyright (c) 1993, 1994, Charles M. Hannum
33 * Copyright (c) 1993, 1994, 1995, Rodney W. Grimes
34 * Copyright (c) 1997, Aaron C. Smith
35 *
36 * See if_ie.c for applicable license.
37 */
38
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD$");
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/lock.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
47 #include <sys/mutex.h>
48 #include <sys/socket.h>
49
50 #include <sys/module.h>
51 #include <sys/bus.h>
52
53 #include <machine/bus.h>
54 #include <machine/resource.h>
55 #include <sys/rman.h>
56
57 #include <machine/md_var.h>
58
59 #include <net/if.h>
60 #include <net/if_media.h>
61
62 #include <isa/isavar.h>
63 #include <isa/pnpvar.h>
64
65 #include <i386/isa/elink.h>
66
67 #include <dev/ic/i82586.h>
68 #include <dev/ie/if_ie507.h>
69 #include <dev/ie/if_iee16.h>
70 #include <dev/ie/if_iereg.h>
71 #include <dev/ie/if_ievar.h>
72
73 static int ie_modevent (module_t, int, void *);
74
75 static void ie_isa_3C507_identify (driver_t *, device_t);
76 static int ie_isa_3C507_probe (device_t);
77 static int ie_isa_3C507_attach (device_t);
78 static int ie_3C507_port_check (u_int32_t);
79
80 static void ie_isa_ee16_identify (driver_t *, device_t);
81 static int ie_isa_ee16_probe (device_t);
82 static int ie_isa_ee16_attach (device_t);
83 static int ie_isa_ee16_shutdown (device_t);
84 static int ie_ee16_port_check (u_int32_t port);
85 static u_int16_t ie_ee16_hw_read_eeprom (u_int32_t port, int loc);
86
87 static int ie_isa_sl_probe (device_t);
88 static int ie_isa_sl_attach (device_t);
89 static enum ie_hardware ie_isa_sl_get_hard_type (u_int32_t);
90
91 /*
92 * 3Com 3C507 Etherlink 16
93 */
94 #define IE_3C507_IOBASE_LOW 0x200
95 #define IE_3C507_IOBASE_HIGH 0x3e0
96 #define IE_3C507_IOSIZE 16
97
98 #define IE_3C507_IRQ_MASK 0x0f
99
100 #define IE_3C507_MADDR_HIGH 0x20
101 #define IE_3C507_MADDR_MASK 0x1c
102 #define IE_3C507_MADDR_BASE 0xc0000
103 #define IE_3C507_MADDR_SHIFT 12
104
105 #define IE_3C507_MSIZE_MASK 3
106 #define IE_3C507_MSIZE_SHIFT 14
107
108 static void
ie_isa_3C507_identify(driver_t * driver,device_t parent)109 ie_isa_3C507_identify (driver_t *driver, device_t parent)
110 {
111 char * desc = "3Com 3C507 Etherlink 16";
112 device_t child;
113 u_int32_t port, maddr, msize;
114 u_int8_t irq, data;
115 int error;
116
117 /* Reset and put card in CONFIG state without changing address. */
118 elink_reset();
119 elink_idseq(ELINK_507_POLY);
120 elink_idseq(ELINK_507_POLY);
121 outb(ELINK_ID_PORT, 0xff);
122
123 for (port = IE_3C507_IOBASE_LOW;
124 port <= IE_3C507_IOBASE_HIGH;
125 port += IE_3C507_IOSIZE) {
126
127 if (ie_3C507_port_check(port)) {
128 #ifdef DEBUG
129 if (bootverbose) {
130 device_printf(parent,
131 "(if_ie) (3C507) not found at port %#x\n",
132 port);
133 }
134 #endif
135 continue;
136 }
137
138 outb(port + IE507_CTRL, EL_CTRL_NRST);
139
140 data = inb(port + IE507_IRQ);
141 irq = data & IE_3C507_IRQ_MASK;
142
143 data = inb(port + IE507_MADDR);
144
145 if (data & IE_3C507_MADDR_HIGH) {
146 if (bootverbose) {
147 device_printf(parent,
148 "(if_ie) can't map 3C507 RAM in high memory\n");
149 }
150 continue;
151 }
152
153 maddr = IE_3C507_MADDR_BASE +
154 ((data & IE_3C507_MADDR_MASK)
155 << IE_3C507_MADDR_SHIFT);
156 msize = ((data & IE_3C507_MSIZE_MASK) + 1)
157 << IE_3C507_MSIZE_SHIFT;
158
159 child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ie", -1);
160 device_set_desc_copy(child, desc);
161 device_set_driver(child, driver);
162
163 error = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
164 if (error) {
165 device_printf(parent, "(if_ie) Unable to set IRQ resource %d.\n",
166 irq);
167 error = device_delete_child(parent, child);
168 continue;
169 }
170
171 error = bus_set_resource(child, SYS_RES_IOPORT, 0, port, IE_3C507_IOSIZE);
172 if (error) {
173 device_printf(parent, "(if_ie) Unable to set IOPORT resource %#x-%#x.\n",
174 port, port+IE_3C507_IOSIZE);
175 error = device_delete_child(parent, child);
176 continue;
177 }
178
179 error = bus_set_resource(child, SYS_RES_MEMORY, 0, maddr, msize);
180 if (error) {
181 device_printf(parent, "(if_ie) Unable to set MEMORY resource %#x-%#x.\n",
182 maddr, maddr+msize);
183 error = device_delete_child(parent, child);
184 continue;
185 }
186
187 if (bootverbose) {
188 device_printf(parent,
189 "(if_ie) <%s> at port %#x-%#x irq %d iomem %#lx-%#lx (%dKB)\n",
190 desc,
191 port, (port + IE_3C507_IOSIZE) - 1,
192 irq,
193 (u_long)maddr, (u_long)(maddr + msize) - 1,
194 (msize / 1024));
195 }
196 }
197
198 /* go to RUN state */
199 outb(ELINK_ID_PORT, 0x00);
200 elink_idseq(ELINK_507_POLY);
201 outb(ELINK_ID_PORT, 0x00);
202
203 return;
204 }
205
206 static int
ie_isa_3C507_probe(device_t dev)207 ie_isa_3C507_probe (device_t dev)
208 {
209 u_int32_t iobase;
210
211 /* No ISA-PnP support */
212 if (isa_get_vendorid(dev)) {
213 return (ENXIO);
214 }
215
216 /* No ISA-HINT support */
217 if (!device_get_desc(dev)) {
218 return (EBUSY);
219 }
220
221 /* Have we at least an ioport? */
222 if ((iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0) {
223 return (ENXIO);
224 }
225
226 /* Is this thing really a 3c507? */
227 if (ie_3C507_port_check(iobase)) {
228 return (ENXIO);
229 }
230
231 return (0);
232 }
233
234 static int
ie_isa_3C507_attach(device_t dev)235 ie_isa_3C507_attach (device_t dev)
236 {
237 struct ie_softc * sc;
238 int error;
239
240 sc = device_get_softc(dev);
241
242 sc->io_rid = 0;
243 sc->irq_rid = 0;
244 sc->mem_rid = 0;
245
246 error = ie_alloc_resources(dev);
247 if (error) {
248 goto bad;
249 }
250
251 sc->bus_use = 0;
252 sc->ie_reset_586 = el_reset_586;
253 sc->ie_chan_attn = el_chan_attn;
254 sc->hard_type = IE_3C507;
255 sc->hard_vers = 0;
256
257 outb(PORT(sc) + IE507_CTRL, EL_CTRL_NORMAL);
258
259 if (!check_ie_present(sc)) {
260 error = ENXIO;
261 goto bad;
262 }
263
264 sl_read_ether(sc, sc->enaddr);
265
266 /* Clear the interrupt latch just in case. */
267 outb(PORT(sc) + IE507_ICTRL, 1);
268
269 error = ie_attach(dev);
270 if (error) {
271 device_printf(dev, "ie_attach() failed.\n");
272 goto bad;
273 }
274
275 return (0);
276 bad:
277 ie_release_resources(dev);
278
279 return (error);
280 }
281
282 /*
283 * If a 3c507 is present, return 0
284 * else, return 1.
285 */
286 static int
ie_3C507_port_check(u_int32_t port)287 ie_3C507_port_check (u_int32_t port)
288 {
289 u_char * signature = "*3COM*";
290 int i;
291
292 for (i = 0; i < 6; i++)
293 if (inb(port + i) != signature[i])
294 return (ENXIO);
295
296 return (0);
297 }
298
299 /*
300 * Intel EtherExpress 16
301 */
302 #define IE_EE16_ID_PORT 0x0f
303 #define IE_EE16_ID 0xbaba
304 #define IE_EE16_EEPROM_CONFIG1 0x00
305 #define IE_EE16_EEPROM_IRQ_MASK 0xe000
306 #define IE_EE16_EEPROM_IRQ_SHIFT 13
307 #define IE_EE16_EEPROM_MEMCFG 0x06
308 #define IE_EE16_IOSIZE 16
309
310 /*
311 * TODO:
312 * Test for 8/16 bit mode.
313 * Test for invalid mem sizes.
314 */
315 static void
ie_isa_ee16_identify(driver_t * driver,device_t parent)316 ie_isa_ee16_identify (driver_t *driver, device_t parent)
317 {
318 char * desc = "Intel EtherExpress 16";
319 device_t child;
320 u_int16_t ports[] = {
321 0x300, 0x310, 0x320, 0x330,
322 0x340, 0x350, 0x360, 0x370,
323 0x200, 0x210, 0x220, 0x230,
324 0x240, 0x250, 0x260, 0x270,
325 0
326 };
327 u_int16_t irqs[] = { 0, 0x09, 0x03, 0x04, 0x05, 0x0a, 0x0b, 0 };
328 u_int32_t port, maddr, msize;
329 u_int8_t irq;
330 u_int16_t data;
331 int i, error;
332
333 for (i = 0; ports[i]; i++) {
334 port = ports[i];
335
336 if (ie_ee16_port_check(port)) {
337 #ifdef DEBUG
338 if (bootverbose) {
339 device_printf(parent,
340 "if_ie: (EE16) not found at port %#x\n",
341 port);
342 }
343 #endif
344 continue;
345 }
346
347 /* reset any ee16 at the current iobase */
348 outb(port + IEE16_ECTRL, IEE16_RESET_ASIC);
349 outb(port + IEE16_ECTRL, 0);
350 DELAY(240);
351
352 data = ie_ee16_hw_read_eeprom(port, IE_EE16_EEPROM_CONFIG1);
353 irq = irqs[((data & IE_EE16_EEPROM_IRQ_MASK)
354 >> IE_EE16_EEPROM_IRQ_SHIFT)];
355
356 data = ie_ee16_hw_read_eeprom(port, IE_EE16_EEPROM_MEMCFG);
357 maddr = 0xc0000 + ((ffs(data & 0x00ff) - 1) * 0x4000);
358 msize = (fls((data & 0x00ff) >> (ffs(data & 0x00ff) - 1)))
359 * 0x4000;
360
361 child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ie", -1);
362 device_set_desc_copy(child, desc);
363 device_set_driver(child, driver);
364
365 error = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
366 if (error) {
367 device_printf(parent, "(if_ie) Unable to set IRQ resource %d.\n",
368 irq);
369 error = device_delete_child(parent, child);
370 continue;
371 }
372
373 error = bus_set_resource(child, SYS_RES_IOPORT, 0, port, IE_EE16_IOSIZE);
374 if (error) {
375 device_printf(parent, "(if_ie) Unable to set IOPORT resource %#x-%#x.\n",
376 port, port+IE_EE16_IOSIZE);
377 error = device_delete_child(parent, child);
378 continue;
379 }
380
381 error = bus_set_resource(child, SYS_RES_MEMORY, 0, maddr, msize);
382 if (error) {
383 device_printf(parent, "(if_ie) Unable to set MEMORY resource %#x-%#x.\n",
384 maddr, maddr+msize);
385 error = device_delete_child(parent, child);
386 continue;
387 }
388
389 if (bootverbose) {
390 device_printf(parent,
391 "if_ie: <%s> at port %#x-%#x irq %d iomem %#lx-%#lx (%dKB)\n",
392 desc,
393 port, (port + IE_EE16_IOSIZE) - 1,
394 irq,
395 (u_long)maddr, (u_long)(maddr + msize) - 1,
396 (msize / 1024));
397 }
398 }
399
400 return;
401 }
402
403 static int
ie_isa_ee16_probe(device_t dev)404 ie_isa_ee16_probe (device_t dev)
405 {
406 u_int32_t iobase;
407
408 /* No ISA-PnP support */
409 if (isa_get_vendorid(dev))
410 return (ENXIO);
411
412 /* No ISA-HINT support */
413 if (!device_get_desc(dev))
414 return (EBUSY);
415
416 /* Have we at least an ioport? */
417 if ((iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0)
418 return (ENXIO);
419
420 /* Is this really an EE16? */
421 if (ie_ee16_port_check(iobase))
422 return (ENXIO);
423
424 return (0);
425 }
426
427 static int
ie_isa_ee16_attach(device_t dev)428 ie_isa_ee16_attach (device_t dev)
429 {
430 struct ie_softc * sc;
431 int i, error;
432 u_int16_t checksum;
433 u_short eaddrtemp, pg, adjust, decode, edecode;
434 u_char bart_config;
435
436 sc = device_get_softc(dev);
437
438 sc->io_rid = 0;
439 sc->irq_rid = 0;
440 sc->mem_rid = 0;
441
442 error = ie_alloc_resources(dev);
443 if (error) {
444 goto bad;
445 }
446
447 sc->bus_use = 0;
448 sc->ie_reset_586 = ee16_reset_586;
449 sc->ie_chan_attn = ee16_chan_attn;
450 sc->hard_type = IE_EE16;
451 sc->hard_vers = 0;
452 sc->iomem = 0;
453
454 /* reset any ee16 at the current iobase */
455 outb(PORT(sc) + IEE16_ECTRL, IEE16_RESET_ASIC);
456 outb(PORT(sc) + IEE16_ECTRL, 0);
457 DELAY(240);
458
459 /* Is this really an EE16? */
460 if (ie_ee16_port_check(PORT(sc))) {
461 device_printf(dev, "ie_ee16_port_check() failed\n");
462 error = ENXIO;
463 goto bad;
464 }
465
466 /* need to put the 586 in RESET while we access the eeprom. */
467 outb(PORT(sc) + IEE16_ECTRL, IEE16_RESET_586);
468
469 /* read the eeprom and checksum it, should == IE_E16_ID */
470 checksum = 0;
471 for (i = 0; i < 0x40; i++)
472 checksum += ie_ee16_hw_read_eeprom(PORT(sc), i);
473
474 if (checksum != IE_EE16_ID) {
475 device_printf(dev, "invalid eeprom checksum: %x\n", checksum);
476 error = ENXIO;
477 goto bad;
478 }
479
480 if ((kvtop(sc->iomembot) < 0xC0000) ||
481 (kvtop(sc->iomembot) + sc->iosize > 0xF0000)) {
482 device_printf(sc->dev, "mapped memory location %p out of range\n",
483 (void *)sc->iomembot);
484 error = ENXIO;
485 goto bad;
486 }
487
488 pg = ((kvtop(sc->iomembot)) & 0x3C000) >> 14;
489 adjust = IEE16_MCTRL_FMCS16 | (pg & 0x3) << 2;
490 decode = ((1 << (sc->iosize / 16384)) - 1) << pg;
491 edecode = ((~decode >> 4) & 0xF0) | (decode >> 8);
492
493 /* ZZZ This should be checked against eeprom location 6, low byte */
494 outb(PORT(sc) + IEE16_MEMDEC, decode & 0xFF);
495 /* ZZZ This should be checked against eeprom location 1, low byte */
496 outb(PORT(sc) + IEE16_MCTRL, adjust);
497 /* ZZZ Now if I could find this one I would have it made */
498 outb(PORT(sc) + IEE16_MPCTRL, (~decode & 0xFF));
499 /* ZZZ I think this is location 6, high byte */
500 outb(PORT(sc) + IEE16_MECTRL, edecode); /* XXX disable Exxx */
501
502 #if 0
503 (void) kvtop(sc->iomembot);
504 #endif
505
506 /*
507 * first prime the stupid bart DRAM controller so that it works,
508 * then zero out all of memory.
509 */
510 bzero(sc->iomembot, 32);
511 bzero(sc->iomembot, sc->iosize);
512
513 /* Get the encoded interrupt number from the EEPROM */
514 sc->irq_encoded = ie_ee16_hw_read_eeprom(PORT(sc),
515 IE_EE16_EEPROM_CONFIG1);
516 sc->irq_encoded = (sc->irq_encoded & IE_EE16_EEPROM_IRQ_MASK) >>
517 IE_EE16_EEPROM_IRQ_SHIFT;
518
519 /*
520 * Get the hardware ethernet address from the EEPROM and save it in
521 * the softc for use by the 586 setup code.
522 */
523 eaddrtemp = ie_ee16_hw_read_eeprom(PORT(sc), IEE16_EEPROM_ENET_HIGH);
524 sc->enaddr[1] = eaddrtemp & 0xFF;
525 sc->enaddr[0] = eaddrtemp >> 8;
526 eaddrtemp = ie_ee16_hw_read_eeprom(PORT(sc), IEE16_EEPROM_ENET_MID);
527 sc->enaddr[3] = eaddrtemp & 0xFF;
528 sc->enaddr[2] = eaddrtemp >> 8;
529 eaddrtemp = ie_ee16_hw_read_eeprom(PORT(sc), IEE16_EEPROM_ENET_LOW);
530 sc->enaddr[5] = eaddrtemp & 0xFF;
531 sc->enaddr[4] = eaddrtemp >> 8;
532
533 /* disable the board interrupts */
534 outb(PORT(sc) + IEE16_IRQ, sc->irq_encoded);
535
536 /* enable loopback to keep bad packets off the wire */
537 bart_config = inb(PORT(sc) + IEE16_CONFIG);
538 bart_config |= IEE16_BART_LOOPBACK;
539 bart_config |= IEE16_BART_MCS16_TEST;/* inb doesn't get bit! */
540 outb(PORT(sc) + IEE16_CONFIG, bart_config);
541 bart_config = inb(PORT(sc) + IEE16_CONFIG);
542
543 /* take the board out of reset state */
544 outb(PORT(sc) + IEE16_ECTRL, 0);
545 DELAY(100);
546
547 if (!check_ie_present(sc)) {
548 device_printf(dev, "check_ie_present() returned false.\n");
549 error = ENXIO;
550 goto bad;
551 }
552
553 error = ie_attach(dev);
554 if (error) {
555 device_printf(dev, "ie_attach() failed.\n");
556 goto bad;
557 }
558
559 return (0);
560 bad:
561 ie_release_resources(dev);
562
563 return (error);
564 }
565
566 static int
ie_isa_ee16_shutdown(device_t dev)567 ie_isa_ee16_shutdown(device_t dev)
568 {
569 struct ie_softc * sc;
570
571 sc = device_get_softc(dev);
572 IE_LOCK(sc);
573 ee16_shutdown(sc);
574 IE_UNLOCK(sc);
575
576 return (0);
577 }
578
579 /*
580 * If an EE16 is present, return 0
581 * else, return 1.
582 */
583 static int
ie_ee16_port_check(u_int32_t port)584 ie_ee16_port_check (u_int32_t port)
585 {
586 int i;
587 u_int16_t board_id;
588 u_int8_t data;
589
590 board_id = 0;
591 for (i = 0; i < 4; i++) {
592 data = inb(port + IE_EE16_ID_PORT);
593 board_id |= ((data >> 4) << ((data & 0x03) << 2));
594 }
595
596 if (board_id != IE_EE16_ID)
597 return (1);
598
599 return (0);
600 }
601
602 static void
ie_ee16_hw_eeprom_clock(u_int32_t port,int state)603 ie_ee16_hw_eeprom_clock (u_int32_t port, int state)
604 {
605 u_int8_t ectrl;
606
607 ectrl = inb(port + IEE16_ECTRL);
608 ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EESK);
609
610 if (state) {
611 ectrl |= IEE16_ECTRL_EESK;
612 }
613 outb(port + IEE16_ECTRL, ectrl);
614 DELAY(9); /* EESK must be stable for 8.38 uSec */
615 }
616
617 static void
ie_ee16_hw_eeprom_out(u_int32_t port,u_int16_t edata,int count)618 ie_ee16_hw_eeprom_out (u_int32_t port, u_int16_t edata, int count)
619 {
620 u_int8_t ectrl;
621 int i;
622
623 ectrl = inb(port + IEE16_ECTRL);
624 ectrl &= ~IEE16_RESET_ASIC;
625
626 for (i = count - 1; i >= 0; i--) {
627 ectrl &= ~IEE16_ECTRL_EEDI;
628 if (edata & (1 << i)) {
629 ectrl |= IEE16_ECTRL_EEDI;
630 }
631 outb(port + IEE16_ECTRL, ectrl);
632 DELAY(1); /* eeprom data must be setup for 0.4 uSec */
633 ie_ee16_hw_eeprom_clock(port, 1);
634 ie_ee16_hw_eeprom_clock(port, 0);
635 }
636 ectrl &= ~IEE16_ECTRL_EEDI;
637 outb(port + IEE16_ECTRL, ectrl);
638 DELAY(1); /* eeprom data must be held for 0.4 uSec */
639
640 return;
641 }
642
643 static u_int16_t
ie_ee16_hw_eeprom_in(u_int32_t port)644 ie_ee16_hw_eeprom_in (u_int32_t port)
645 {
646 u_int8_t ectrl;
647 u_int16_t edata;
648 int i;
649
650 ectrl = inb(port + IEE16_ECTRL);
651 ectrl &= ~IEE16_RESET_ASIC;
652
653 for (edata = 0, i = 0; i < 16; i++) {
654 edata = edata << 1;
655 ie_ee16_hw_eeprom_clock(port, 1);
656 ectrl = inb(port + IEE16_ECTRL);
657 if (ectrl & IEE16_ECTRL_EEDO) {
658 edata |= 1;
659 }
660 ie_ee16_hw_eeprom_clock(port, 0);
661 }
662 return (edata);
663 }
664
665 static u_int16_t
ie_ee16_hw_read_eeprom(u_int32_t port,int loc)666 ie_ee16_hw_read_eeprom (u_int32_t port, int loc)
667 {
668 u_int8_t ectrl;
669 u_int16_t edata;
670
671 ectrl = inb(port + IEE16_ECTRL);
672 ectrl &= IEE16_ECTRL_MASK;
673 ectrl |= IEE16_ECTRL_EECS;
674 outb(port + IEE16_ECTRL, ectrl);
675
676 ie_ee16_hw_eeprom_out(port, IEE16_EEPROM_READ, IEE16_EEPROM_OPSIZE1);
677 ie_ee16_hw_eeprom_out(port, loc, IEE16_EEPROM_ADDR_SIZE);
678 edata = ie_ee16_hw_eeprom_in(port);
679
680 ectrl = inb(port + IEE16_ECTRL);
681 ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EEDI | IEE16_ECTRL_EECS);
682 outb(port + IEE16_ECTRL, ectrl);
683
684 ie_ee16_hw_eeprom_clock(port, 1);
685 ie_ee16_hw_eeprom_clock(port, 0);
686
687 return (edata);
688 }
689
690 /*
691 * AT&T StarLan/
692 */
693
694 static int
ie_isa_sl_probe(device_t dev)695 ie_isa_sl_probe (device_t dev)
696 {
697 u_int32_t iobase;
698
699 /* No ISA-PnP support */
700 if (isa_get_vendorid(dev))
701 return (ENXIO);
702
703 /* ISA-HINT support only! */
704 if (device_get_desc(dev))
705 return (EBUSY);
706
707 /* Have we at least an ioport? */
708 if ((iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0)
709 return (ENXIO);
710
711 /* Is this really an SL board? */
712 if (ie_isa_sl_get_hard_type(iobase) == IE_NONE)
713 return (ENXIO);
714
715 return (ENXIO);
716 }
717
718 static int
ie_isa_sl_attach(device_t dev)719 ie_isa_sl_attach (device_t dev)
720 {
721 struct ie_softc * sc;
722 int error;
723
724 sc = device_get_softc(dev);
725
726 sc->io_rid = 0;
727 sc->irq_rid = 0;
728 sc->mem_rid = 0;
729
730 error = ie_alloc_resources(dev);
731 if (error) {
732 goto bad;
733 }
734
735 /* Is this really an SL board? */
736 if ((sc->hard_type = ie_isa_sl_get_hard_type(PORT(sc))) == IE_NONE) {
737 error = ENXIO;
738 goto bad;
739 }
740
741 sc->hard_vers = SL_REV(inb(PORT(sc) + IEATT_REVISION));
742 if (sc->hard_type == IE_NI5210) {
743 sc->bus_use = 1;
744 } else {
745 sc->bus_use = 0;
746 }
747
748 sc->ie_reset_586 = sl_reset_586;
749 sc->ie_chan_attn = sl_chan_attn;
750
751 if (!check_ie_present(sc)) {
752 error = ENXIO;
753 goto bad;
754 }
755
756 switch (sc->hard_type) {
757 case IE_EN100:
758 case IE_STARLAN10:
759 case IE_SLFIBER:
760 case IE_NI5210:
761 sl_read_ether(sc, sc->enaddr);
762 break;
763 default:
764 if (bootverbose)
765 device_printf(sc->dev, "unknown AT&T board type code %d\n", sc->hard_type);
766 error = ENXIO;
767 goto bad;
768 break;
769 }
770
771 error = ie_attach(dev);
772 if (error) {
773 device_printf(dev, "ie_attach() failed.\n");
774 goto bad;
775 }
776
777 return (0);
778 bad:
779 ie_release_resources(dev);
780
781 return (error);
782 }
783
784 static enum ie_hardware
ie_isa_sl_get_hard_type(u_int32_t port)785 ie_isa_sl_get_hard_type (u_int32_t port)
786 {
787 u_char c;
788 enum ie_hardware retval;
789
790 c = inb(port + IEATT_REVISION);
791 switch (SL_BOARD(c)) {
792 case SL1_BOARD:
793 if (inb(port + IEATT_ATTRIB) != NI5210_BOARD)
794 retval = IE_NONE;
795 retval = IE_NI5210;
796 break;
797 case SL10_BOARD:
798 retval = IE_STARLAN10;
799 break;
800 case EN100_BOARD:
801 retval = IE_EN100;
802 break;
803 case SLFIBER_BOARD:
804 retval = IE_SLFIBER;
805 break;
806 default:
807 retval = IE_NONE;
808 }
809 return (retval);
810 }
811
812 static devclass_t ie_devclass;
813
814 static device_method_t ie_isa_3C507_methods[] = {
815 DEVMETHOD(device_identify, ie_isa_3C507_identify),
816 DEVMETHOD(device_probe, ie_isa_3C507_probe),
817 DEVMETHOD(device_attach, ie_isa_3C507_attach),
818 DEVMETHOD(device_detach, ie_detach),
819 { 0, 0 }
820 };
821
822 static driver_t ie_isa_3C507_driver = {
823 "ie",
824 ie_isa_3C507_methods,
825 sizeof(struct ie_softc),
826 };
827
828 DRIVER_MODULE(ie_3C507, isa, ie_isa_3C507_driver, ie_devclass, ie_modevent, 0);
829 MODULE_DEPEND(ie_3C507, elink, 1, 1, 1);
830
831 static device_method_t ie_isa_ee16_methods[] = {
832 DEVMETHOD(device_identify, ie_isa_ee16_identify),
833 DEVMETHOD(device_probe, ie_isa_ee16_probe),
834 DEVMETHOD(device_attach, ie_isa_ee16_attach),
835 DEVMETHOD(device_shutdown, ie_isa_ee16_shutdown),
836 DEVMETHOD(device_detach, ie_detach),
837 { 0, 0 }
838 };
839
840 static driver_t ie_isa_ee16_driver = {
841 "ie",
842 ie_isa_ee16_methods,
843 sizeof(struct ie_softc),
844 };
845
846 DRIVER_MODULE(ie, isa, ie_isa_ee16_driver, ie_devclass, ie_modevent, 0);
847
848 static device_method_t ie_isa_sl_methods[] = {
849 DEVMETHOD(device_probe, ie_isa_sl_probe),
850 DEVMETHOD(device_attach, ie_isa_sl_attach),
851 DEVMETHOD(device_detach, ie_detach),
852 { 0, 0 }
853 };
854
855 static driver_t ie_isa_sl_driver = {
856 "ie",
857 ie_isa_sl_methods,
858 sizeof(struct ie_softc),
859 };
860
861 DRIVER_MODULE(ie_SL, isa, ie_isa_sl_driver, ie_devclass, ie_modevent, 0);
862
863 static int
ie_modevent(mod,what,arg)864 ie_modevent (mod, what, arg)
865 module_t mod;
866 int what;
867 void * arg;
868 {
869 device_t * devs;
870 int count;
871 int i;
872
873 switch (what) {
874 case MOD_LOAD:
875 break;
876 case MOD_UNLOAD:
877 devclass_get_devices(ie_devclass, &devs, &count);
878 for (i = 0; i < count; i++)
879 device_delete_child(device_get_parent(devs[i]), devs[i]);
880 free(devs, M_TEMP);
881 break;
882 default:
883 break;
884 }
885
886 return (0);
887 }
888