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