Annotation of src/sys/dev/isa/if_ate.c, Revision 1.41
1.41 ! abs 1: /* $NetBSD: if_ate.c,v 1.40 2004/09/14 20:20:47 drochner Exp $ */
1.19 perry 2:
1.1 mycroft 3: /*
4: * All Rights Reserved, Copyright (C) Fujitsu Limited 1995
5: *
6: * This software may be used, modified, copied, distributed, and sold, in
7: * both source and binary form provided that the above copyright, these
8: * terms and the following disclaimer are retained. The name of the author
9: * and/or the contributor may not be used to endorse or promote products
10: * derived from this software without specific prior written permission.
11: *
12: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND
13: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE
16: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION.
19: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22: * SUCH DAMAGE.
23: */
24:
25: /*
26: * Portions copyright (C) 1993, David Greenman. This software may be used,
27: * modified, copied, distributed, and sold, in both source and binary form
28: * provided that the above copyright and these terms are retained. Under no
29: * circumstances is the author responsible for the proper functioning of this
30: * software, nor does the author assume any responsibility for damages
31: * incurred with its use.
32: */
1.28 lukem 33:
34: #include <sys/cdefs.h>
1.41 ! abs 35: __KERNEL_RCSID(0, "$NetBSD: if_ate.c,v 1.40 2004/09/14 20:20:47 drochner Exp $");
1.1 mycroft 36:
37: #include <sys/param.h>
38: #include <sys/systm.h>
1.21 enami 39: #include <sys/device.h>
1.1 mycroft 40: #include <sys/socket.h>
41: #include <sys/syslog.h>
42:
43: #include <net/if.h>
1.17 is 44: #include <net/if_ether.h>
1.21 enami 45: #include <net/if_media.h>
1.1 mycroft 46:
1.21 enami 47: #include <machine/bus.h>
1.13 mycroft 48: #include <machine/intr.h>
1.1 mycroft 49:
1.3 cgd 50: #include <dev/ic/mb86960reg.h>
1.21 enami 51: #include <dev/ic/mb86960var.h>
1.1 mycroft 52:
1.21 enami 53: #include <dev/isa/isavar.h>
1.1 mycroft 54:
1.21 enami 55: int ate_match __P((struct device *, struct cfdata *, void *));
56: void ate_attach __P((struct device *, struct device *, void *));
1.1 mycroft 57:
1.21 enami 58: struct ate_softc {
59: struct mb86960_softc sc_mb86960; /* real "mb86960" softc */
1.1 mycroft 60:
1.21 enami 61: /* ISA-specific goo. */
62: void *sc_ih; /* interrupt cookie */
63: };
1.1 mycroft 64:
1.35 thorpej 65: CFATTACH_DECL(ate_isa, sizeof(struct ate_softc),
66: ate_match, ate_attach, NULL, NULL);
1.1 mycroft 67:
1.21 enami 68: struct fe_simple_probe_struct {
69: u_char port; /* Offset from the base I/O address. */
70: u_char mask; /* Bits to be checked. */
71: u_char bits; /* Values to be compared against. */
1.1 mycroft 72: };
73:
1.21 enami 74: static __inline__ int fe_simple_probe __P((bus_space_tag_t,
75: bus_space_handle_t, struct fe_simple_probe_struct const *));
76: static int ate_find __P((bus_space_tag_t, bus_space_handle_t, int *,
77: int *));
78: static int ate_detect __P((bus_space_tag_t, bus_space_handle_t,
79: u_int8_t enaddr[ETHER_ADDR_LEN]));
1.1 mycroft 80:
1.21 enami 81: static int const ate_iomap[8] = {
82: 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300
83: };
84: #define NATE_IOMAP (sizeof (ate_iomap) / sizeof (ate_iomap[0]))
85: #define ATE_NPORTS 0x20
1.1 mycroft 86:
87: /*
88: * Hardware probe routines.
89: */
90:
91: /*
92: * Determine if the device is present.
93: */
94: int
1.21 enami 95: ate_match(parent, match, aux)
1.1 mycroft 96: struct device *parent;
1.21 enami 97: struct cfdata *match;
98: void *aux;
1.1 mycroft 99: {
100: struct isa_attach_args *ia = aux;
1.21 enami 101: bus_space_tag_t iot = ia->ia_iot;
102: bus_space_handle_t ioh;
103: int i, iobase, irq, rv = 0;
104: u_int8_t myea[ETHER_ADDR_LEN];
105:
1.30 thorpej 106: if (ia->ia_nio < 1)
107: return (0);
108: if (ia->ia_nirq < 1)
109: return (0);
110:
111: if (ISA_DIRECT_CONFIG(ia))
112: return (0);
113:
1.21 enami 114: /* Disallow wildcarded values. */
1.40 drochner 115: if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT)
1.21 enami 116: return (0);
117:
118: /*
119: * See if the sepcified address is valid for MB86965A JLI mode.
120: */
121: for (i = 0; i < NATE_IOMAP; i++)
1.30 thorpej 122: if (ate_iomap[i] == ia->ia_io[0].ir_addr)
1.21 enami 123: break;
124: if (i == NATE_IOMAP) {
1.23 enami 125: #ifdef ATE_DEBUG
1.21 enami 126: printf("ate_match: unknown iobase 0x%x\n", ia->ia_iobase);
127: #endif
128: return (0);
129: }
130:
131: /* Map i/o space. */
1.30 thorpej 132: if (bus_space_map(iot, ia->ia_io[0].ir_addr, ATE_NPORTS, 0, &ioh)) {
1.23 enami 133: #ifdef ATE_DEBUG
1.21 enami 134: printf("ate_match: couldn't map iospace 0x%x\n",
1.30 thorpej 135: ia->ia_io[0].ir_addr);
1.21 enami 136: #endif
137: return (0);
138: }
1.1 mycroft 139:
1.21 enami 140: if (ate_find(iot, ioh, &iobase, &irq) == 0) {
1.23 enami 141: #ifdef ATE_DEBUG
1.21 enami 142: printf("ate_match: ate_find failed\n");
1.1 mycroft 143: #endif
1.21 enami 144: goto out;
145: }
146:
1.30 thorpej 147: if (iobase != ia->ia_io[0].ir_addr) {
1.23 enami 148: #ifdef ATE_DEBUG
1.21 enami 149: printf("ate_match: unexpected iobase in board: 0x%x\n",
150: ia->ia_iobase);
151: #endif
152: goto out;
153: }
154:
155: if (ate_detect(iot, ioh, myea) == 0) { /* XXX necessary? */
1.23 enami 156: #ifdef ATE_DEBUG
1.21 enami 157: printf("ate_match: ate_detect failed\n");
158: #endif
159: goto out;
160: }
161:
1.40 drochner 162: if (ia->ia_irq[0].ir_irq != ISA_UNKNOWN_IRQ) {
1.30 thorpej 163: if (ia->ia_irq[0].ir_irq != irq) {
1.21 enami 164: printf("ate_match: irq mismatch; "
165: "kernel configured %d != board configured %d\n",
1.30 thorpej 166: ia->ia_irq[0].ir_irq, irq);
1.21 enami 167: goto out;
168: }
169: } else
1.30 thorpej 170: ia->ia_irq[0].ir_irq = irq;
171:
172: ia->ia_nio = 1;
173: ia->ia_io[0].ir_size = ATE_NPORTS;
174:
175: ia->ia_nirq = 1;
176:
177: ia->ia_niomem = 0;
178: ia->ia_ndrq = 0;
1.1 mycroft 179:
1.21 enami 180: rv = 1;
1.1 mycroft 181:
1.21 enami 182: out:
183: bus_space_unmap(iot, ioh, ATE_NPORTS);
184: return (rv);
1.1 mycroft 185: }
186:
187: /*
188: * Check for specific bits in specific registers have specific values.
189: */
1.21 enami 190: static __inline__ int
191: fe_simple_probe (iot, ioh, sp)
192: bus_space_tag_t iot;
193: bus_space_handle_t ioh;
194: struct fe_simple_probe_struct const *sp;
1.1 mycroft 195: {
1.21 enami 196: u_int8_t val;
197: struct fe_simple_probe_struct const *p;
1.1 mycroft 198:
199: for (p = sp; p->mask != 0; p++) {
1.21 enami 200: val = bus_space_read_1(iot, ioh, p->port);
201: if ((val & p->mask) != p->bits) {
1.23 enami 202: #ifdef ATE_DEBUG
1.21 enami 203: printf("fe_simple_probe: %x & %x != %x\n",
204: val, p->mask, p->bits);
205: #endif
1.1 mycroft 206: return (0);
207: }
208: }
1.21 enami 209:
1.1 mycroft 210: return (1);
211: }
212:
213: /*
214: * Hardware (vendor) specific probe routines.
215: */
216:
217: /*
218: * Probe and initialization for Allied-Telesis AT1700/RE2000 series.
219: */
1.21 enami 220: static int
221: ate_find(iot, ioh, iobase, irq)
222: bus_space_tag_t iot;
223: bus_space_handle_t ioh;
224: int *iobase, *irq;
1.1 mycroft 225: {
1.36 tsutsui 226: u_int8_t eeprom[FE_EEPROM_SIZE];
1.21 enami 227: int n;
1.1 mycroft 228:
229: static int const irqmap[4][4] = {
230: { 3, 4, 5, 9 },
231: { 10, 11, 12, 15 },
232: { 3, 11, 5, 15 },
233: { 10, 11, 14, 15 },
234: };
235: static struct fe_simple_probe_struct const probe_table[] = {
236: { FE_DLCR2, 0x70, 0x00 },
237: { FE_DLCR4, 0x08, 0x00 },
238: { FE_DLCR5, 0x80, 0x00 },
239: #if 0
240: { FE_BMPR16, 0x1B, 0x00 },
241: { FE_BMPR17, 0x7F, 0x00 },
242: #endif
243: { 0 }
244: };
245:
1.23 enami 246: #if ATE_DEBUG >= 4
1.36 tsutsui 247: log(LOG_INFO, "ate_find: probe (0x%x) for ATE\n", iobase);
1.1 mycroft 248: #if 0
1.21 enami 249: fe_dump(LOG_INFO, sc);
1.1 mycroft 250: #endif
251: #endif
252:
253: /*
254: * We should test if MB86965A is on the base address now.
255: * Unfortunately, it is very hard to probe it reliably, since
256: * we have no way to reset the chip under software control.
257: * On cold boot, we could check the "signature" bit patterns
258: * described in the Fujitsu document. On warm boot, however,
259: * we can predict almost nothing about register values.
260: */
1.21 enami 261: if (!fe_simple_probe(iot, ioh, probe_table))
1.1 mycroft 262: return (0);
263:
264: /* Check if our I/O address matches config info on 86965. */
1.21 enami 265: n = (bus_space_read_1(iot, ioh, FE_BMPR19) & FE_B19_ADDR)
266: >> FE_B19_ADDR_SHIFT;
267: *iobase = ate_iomap[n];
1.1 mycroft 268:
269: /*
270: * We are now almost sure we have an AT1700 at the given
271: * address. So, read EEPROM through 86965. We have to write
272: * into LSI registers to read from EEPROM. I want to avoid it
1.29 wiz 273: * at this stage, but I cannot test the presence of the chip
1.1 mycroft 274: * any further without reading EEPROM. FIXME.
275: */
1.36 tsutsui 276: mb86965_read_eeprom(iot, ioh, eeprom);
1.1 mycroft 277:
278: /* Make sure that config info in EEPROM and 86965 agree. */
1.21 enami 279: if (eeprom[FE_EEPROM_CONF] != bus_space_read_1(iot, ioh, FE_BMPR19)) {
280: #ifdef DIAGNOSTIC
281: printf("ate_find: "
1.41 ! abs 282: "incorrect configuration in eeprom and chip\n");
1.21 enami 283: #endif
284: return (0);
1.1 mycroft 285: }
286:
287: /*
288: * Try to determine IRQ settings.
289: * Different models use different ranges of IRQs.
290: */
1.21 enami 291: n = (bus_space_read_1(iot, ioh, FE_BMPR19) & FE_B19_IRQ)
292: >> FE_B19_IRQ_SHIFT;
1.1 mycroft 293: switch (eeprom[FE_ATI_EEP_REVISION] & 0xf0) {
294: case 0x30:
1.21 enami 295: *irq = irqmap[3][n];
1.1 mycroft 296: break;
297: case 0x10:
298: case 0x50:
1.21 enami 299: *irq = irqmap[2][n];
1.1 mycroft 300: break;
301: case 0x40:
302: case 0x60:
303: if (eeprom[FE_ATI_EEP_MAGIC] & 0x04) {
1.21 enami 304: *irq = irqmap[1][n];
1.1 mycroft 305: break;
306: }
307: default:
1.21 enami 308: *irq = irqmap[0][n];
1.1 mycroft 309: break;
310: }
311:
1.21 enami 312: return (1);
313: }
1.1 mycroft 314:
1.21 enami 315: /*
316: * Determine type and ethernet address.
317: */
318: static int
319: ate_detect(iot, ioh, enaddr)
320: bus_space_tag_t iot;
321: bus_space_handle_t ioh;
322: u_int8_t enaddr[ETHER_ADDR_LEN];
323: {
1.36 tsutsui 324: u_int8_t eeprom[FE_EEPROM_SIZE];
1.21 enami 325: int type;
1.1 mycroft 326:
327: /* Get our station address from EEPROM. */
1.36 tsutsui 328: mb86965_read_eeprom(iot, ioh, eeprom);
1.27 thorpej 329: memcpy(enaddr, eeprom + FE_ATI_EEP_ADDR, ETHER_ADDR_LEN);
1.1 mycroft 330:
331: /* Make sure we got a valid station address. */
1.21 enami 332: if ((enaddr[0] & 0x03) != 0x00 ||
333: (enaddr[0] == 0x00 && enaddr[1] == 0x00 && enaddr[2] == 0x00)) {
1.23 enami 334: #ifdef ATE_DEBUG
1.36 tsutsui 335: printf("ate_detect: invalid ethernet address\n");
1.1 mycroft 336: #endif
1.21 enami 337: return (0);
338: }
1.1 mycroft 339:
340: /*
1.21 enami 341: * Determine the card type.
1.1 mycroft 342: */
1.21 enami 343: switch (eeprom[FE_ATI_EEP_MODEL]) {
344: case FE_ATI_MODEL_AT1700T:
345: type = FE_TYPE_AT1700T;
346: break;
347: case FE_ATI_MODEL_AT1700BT:
348: type = FE_TYPE_AT1700BT;
349: break;
350: case FE_ATI_MODEL_AT1700FT:
351: type = FE_TYPE_AT1700FT;
352: break;
353: case FE_ATI_MODEL_AT1700AT:
354: type = FE_TYPE_AT1700AT;
355: break;
356: default:
1.37 tsutsui 357: type = FE_TYPE_AT_UNKNOWN;
1.21 enami 358: break;
359: }
1.1 mycroft 360:
1.21 enami 361: return (type);
362: }
1.1 mycroft 363:
1.21 enami 364: void
365: ate_attach(parent, self, aux)
366: struct device *parent, *self;
367: void *aux;
368: {
369: struct ate_softc *isc = (struct ate_softc *)self;
370: struct mb86960_softc *sc = &isc->sc_mb86960;
371: struct isa_attach_args *ia = aux;
372: bus_space_tag_t iot = ia->ia_iot;
373: bus_space_handle_t ioh;
374: u_int8_t myea[ETHER_ADDR_LEN];
375: const char *typestr;
376: int type;
377:
378: /* Map i/o space. */
1.30 thorpej 379: if (bus_space_map(iot, ia->ia_io[0].ir_addr, ATE_NPORTS, 0, &ioh)) {
1.38 tsutsui 380: printf(": can't map i/o space\n");
1.21 enami 381: return;
382: }
1.1 mycroft 383:
1.21 enami 384: sc->sc_bst = iot;
385: sc->sc_bsh = ioh;
1.1 mycroft 386:
1.26 jdolecek 387: /* Determine the card type and get ethernet address. */
1.21 enami 388: type = ate_detect(iot, ioh, myea);
389: switch (type) {
390: case FE_TYPE_AT1700T:
1.37 tsutsui 391: typestr = "AT-1700T/RE2001";
1.21 enami 392: break;
393: case FE_TYPE_AT1700BT:
1.37 tsutsui 394: typestr = "AT-1700BT/RE2003";
1.21 enami 395: break;
396: case FE_TYPE_AT1700FT:
1.37 tsutsui 397: typestr = "AT-1700FT/RE2009";
1.21 enami 398: break;
399: case FE_TYPE_AT1700AT:
1.37 tsutsui 400: typestr = "AT-1700AT/RE2005";
1.21 enami 401: break;
1.37 tsutsui 402: case FE_TYPE_AT_UNKNOWN:
403: typestr = "unknown AT-1700/RE2000";
1.1 mycroft 404: break;
405:
406: default:
1.21 enami 407: /* Unknown card type: maybe a new model, but... */
1.38 tsutsui 408: printf(": where did the card go?!\n");
1.21 enami 409: panic("unknown card");
1.1 mycroft 410: }
411:
1.38 tsutsui 412: printf(": %s Ethernet\n", typestr);
1.1 mycroft 413:
1.21 enami 414: /* This interface is always enabled. */
1.39 tsutsui 415: sc->sc_stat |= FE_STAT_ENABLED;
1.1 mycroft 416:
417: /*
1.21 enami 418: * Do generic MB86960 attach.
1.1 mycroft 419: */
1.39 tsutsui 420: mb86960_attach(sc, myea);
1.1 mycroft 421:
1.21 enami 422: mb86960_config(sc, NULL, 0, 0);
1.1 mycroft 423:
1.21 enami 424: /* Establish the interrupt handler. */
1.30 thorpej 425: isc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq,
426: IST_EDGE, IPL_NET, mb86960_intr, sc);
1.21 enami 427: if (isc->sc_ih == NULL)
428: printf("%s: couldn't establish interrupt handler\n",
429: sc->sc_dev.dv_xname);
1.1 mycroft 430: }
CVSweb <webmaster@jp.NetBSD.org>