1 /* $NetBSD: if_ate.c,v 1.24 2000/05/29 17:37:17 jhawk Exp $ */ 2 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 */ 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/device.h> 37 #include <sys/socket.h> 38 #include <sys/syslog.h> 39 40 #include <net/if.h> 41 #include <net/if_ether.h> 42 #include <net/if_media.h> 43 44 #include <machine/bus.h> 45 #include <machine/intr.h> 46 47 #include <dev/ic/mb86960reg.h> 48 #include <dev/ic/mb86960var.h> 49 50 #include <dev/isa/isavar.h> 51 #include <dev/isa/if_fereg.h> /* XXX */ 52 53 int ate_match __P((struct device *, struct cfdata *, void *)); 54 void ate_attach __P((struct device *, struct device *, void *)); 55 56 struct ate_softc { 57 struct mb86960_softc sc_mb86960; /* real "mb86960" softc */ 58 59 /* ISA-specific goo. */ 60 void *sc_ih; /* interrupt cookie */ 61 }; 62 63 struct cfattach ate_ca = { 64 sizeof(struct ate_softc), ate_match, ate_attach 65 }; 66 67 #if NetBSD <= 199712 68 struct cfdriver ate_cd = { 69 NULL, "ate", DV_IFNET 70 }; 71 #endif 72 73 struct fe_simple_probe_struct { 74 u_char port; /* Offset from the base I/O address. */ 75 u_char mask; /* Bits to be checked. */ 76 u_char bits; /* Values to be compared against. */ 77 }; 78 79 static __inline__ int fe_simple_probe __P((bus_space_tag_t, 80 bus_space_handle_t, struct fe_simple_probe_struct const *)); 81 static __inline__ void ate_strobe __P((bus_space_tag_t, bus_space_handle_t)); 82 static void ate_read_eeprom __P((bus_space_tag_t, bus_space_handle_t, 83 u_char *)); 84 static int ate_find __P((bus_space_tag_t, bus_space_handle_t, int *, 85 int *)); 86 static int ate_detect __P((bus_space_tag_t, bus_space_handle_t, 87 u_int8_t enaddr[ETHER_ADDR_LEN])); 88 89 static int const ate_iomap[8] = { 90 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300 91 }; 92 #define NATE_IOMAP (sizeof (ate_iomap) / sizeof (ate_iomap[0])) 93 #define ATE_NPORTS 0x20 94 95 /* 96 * Hardware probe routines. 97 */ 98 99 /* 100 * Determine if the device is present. 101 */ 102 int 103 ate_match(parent, match, aux) 104 struct device *parent; 105 struct cfdata *match; 106 void *aux; 107 { 108 struct isa_attach_args *ia = aux; 109 bus_space_tag_t iot = ia->ia_iot; 110 bus_space_handle_t ioh; 111 int i, iobase, irq, rv = 0; 112 u_int8_t myea[ETHER_ADDR_LEN]; 113 114 /* Disallow wildcarded values. */ 115 if (ia->ia_iobase == ISACF_PORT_DEFAULT) 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++) 122 if (ate_iomap[i] == ia->ia_iobase) 123 break; 124 if (i == NATE_IOMAP) { 125 #ifdef ATE_DEBUG 126 printf("ate_match: unknown iobase 0x%x\n", ia->ia_iobase); 127 #endif 128 return (0); 129 } 130 131 /* Map i/o space. */ 132 if (bus_space_map(iot, ia->ia_iobase, ATE_NPORTS, 0, &ioh)) { 133 #ifdef ATE_DEBUG 134 printf("ate_match: couldn't map iospace 0x%x\n", 135 ia->ia_iobase); 136 #endif 137 return (0); 138 } 139 140 if (ate_find(iot, ioh, &iobase, &irq) == 0) { 141 #ifdef ATE_DEBUG 142 printf("ate_match: ate_find failed\n"); 143 #endif 144 goto out; 145 } 146 147 if (iobase != ia->ia_iobase) { 148 #ifdef ATE_DEBUG 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? */ 156 #ifdef ATE_DEBUG 157 printf("ate_match: ate_detect failed\n"); 158 #endif 159 goto out; 160 } 161 162 if (ia->ia_irq != ISACF_IRQ_DEFAULT) { 163 if (ia->ia_irq != irq) { 164 printf("ate_match: irq mismatch; " 165 "kernel configured %d != board configured %d\n", 166 ia->ia_irq, irq); 167 goto out; 168 } 169 } else 170 ia->ia_irq = irq; 171 172 ia->ia_iosize = ATE_NPORTS; 173 ia->ia_msize = 0; 174 rv = 1; 175 176 out: 177 bus_space_unmap(iot, ioh, ATE_NPORTS); 178 return (rv); 179 } 180 181 /* 182 * Check for specific bits in specific registers have specific values. 183 */ 184 static __inline__ int 185 fe_simple_probe (iot, ioh, sp) 186 bus_space_tag_t iot; 187 bus_space_handle_t ioh; 188 struct fe_simple_probe_struct const *sp; 189 { 190 u_int8_t val; 191 struct fe_simple_probe_struct const *p; 192 193 for (p = sp; p->mask != 0; p++) { 194 val = bus_space_read_1(iot, ioh, p->port); 195 if ((val & p->mask) != p->bits) { 196 #ifdef ATE_DEBUG 197 printf("fe_simple_probe: %x & %x != %x\n", 198 val, p->mask, p->bits); 199 #endif 200 return (0); 201 } 202 } 203 204 return (1); 205 } 206 207 /* 208 * Routines to read all bytes from the config EEPROM through MB86965A. 209 * I'm not sure what exactly I'm doing here... I was told just to follow 210 * the steps, and it worked. Could someone tell me why the following 211 * code works? (Or, why all similar codes I tried previously doesn't 212 * work.) FIXME. 213 */ 214 215 static __inline__ void 216 ate_strobe (iot, ioh) 217 bus_space_tag_t iot; 218 bus_space_handle_t ioh; 219 { 220 221 /* 222 * Output same value twice. To speed-down execution? 223 */ 224 bus_space_write_1(iot, ioh, FE_BMPR16, FE_B16_SELECT); 225 bus_space_write_1(iot, ioh, FE_BMPR16, FE_B16_SELECT); 226 bus_space_write_1(iot, ioh, FE_BMPR16, FE_B16_SELECT | FE_B16_CLOCK); 227 bus_space_write_1(iot, ioh, FE_BMPR16, FE_B16_SELECT | FE_B16_CLOCK); 228 bus_space_write_1(iot, ioh, FE_BMPR16, FE_B16_SELECT); 229 bus_space_write_1(iot, ioh, FE_BMPR16, FE_B16_SELECT); 230 } 231 232 static void 233 ate_read_eeprom(iot, ioh, data) 234 bus_space_tag_t iot; 235 bus_space_handle_t ioh; 236 u_char *data; 237 { 238 int n, count; 239 u_char val, bit; 240 241 /* Read bytes from EEPROM; two bytes per an iterration. */ 242 for (n = 0; n < FE_EEPROM_SIZE / 2; n++) { 243 /* Reset the EEPROM interface. */ 244 bus_space_write_1(iot, ioh, FE_BMPR16, 0x00); 245 bus_space_write_1(iot, ioh, FE_BMPR17, 0x00); 246 bus_space_write_1(iot, ioh, FE_BMPR16, FE_B16_SELECT); 247 248 /* Start EEPROM access. */ 249 bus_space_write_1(iot, ioh, FE_BMPR17, FE_B17_DATA); 250 ate_strobe(iot, ioh); 251 252 /* Pass the iterration count to the chip. */ 253 count = 0x80 | n; 254 for (bit = 0x80; bit != 0x00; bit >>= 1) { 255 bus_space_write_1(iot, ioh, FE_BMPR17, 256 (count & bit) ? FE_B17_DATA : 0); 257 ate_strobe(iot, ioh); 258 } 259 bus_space_write_1(iot, ioh, FE_BMPR17, 0x00); 260 261 /* Read a byte. */ 262 val = 0; 263 for (bit = 0x80; bit != 0x00; bit >>= 1) { 264 ate_strobe(iot, ioh); 265 if (bus_space_read_1(iot, ioh, FE_BMPR17) & 266 FE_B17_DATA) 267 val |= bit; 268 } 269 *data++ = val; 270 271 /* Read one more byte. */ 272 val = 0; 273 for (bit = 0x80; bit != 0x00; bit >>= 1) { 274 ate_strobe(iot, ioh); 275 if (bus_space_read_1(iot, ioh, FE_BMPR17) & 276 FE_B17_DATA) 277 val |= bit; 278 } 279 *data++ = val; 280 } 281 282 /* Make sure the EEPROM is turned off. */ 283 bus_space_write_1(iot, ioh, FE_BMPR16, 0); 284 bus_space_write_1(iot, ioh, FE_BMPR17, 0); 285 286 #if ATE_DEBUG >= 3 287 /* Report what we got. */ 288 data -= FE_EEPROM_SIZE; 289 log(LOG_INFO, "ate_read_eeprom: EEPROM at %04x:" 290 " %02x%02x%02x%02x %02x%02x%02x%02x -" 291 " %02x%02x%02x%02x %02x%02x%02x%02x -" 292 " %02x%02x%02x%02x %02x%02x%02x%02x -" 293 " %02x%02x%02x%02x %02x%02x%02x%02x\n", 294 (int) ioh, /* XXX */ 295 data[ 0], data[ 1], data[ 2], data[ 3], 296 data[ 4], data[ 5], data[ 6], data[ 7], 297 data[ 8], data[ 9], data[10], data[11], 298 data[12], data[13], data[14], data[15], 299 data[16], data[17], data[18], data[19], 300 data[20], data[21], data[22], data[23], 301 data[24], data[25], data[26], data[27], 302 data[28], data[29], data[30], data[31]); 303 #endif 304 } 305 306 /* 307 * Hardware (vendor) specific probe routines. 308 */ 309 310 /* 311 * Probe and initialization for Allied-Telesis AT1700/RE2000 series. 312 */ 313 static int 314 ate_find(iot, ioh, iobase, irq) 315 bus_space_tag_t iot; 316 bus_space_handle_t ioh; 317 int *iobase, *irq; 318 { 319 u_char eeprom[FE_EEPROM_SIZE]; 320 int n; 321 322 static int const irqmap[4][4] = { 323 { 3, 4, 5, 9 }, 324 { 10, 11, 12, 15 }, 325 { 3, 11, 5, 15 }, 326 { 10, 11, 14, 15 }, 327 }; 328 static struct fe_simple_probe_struct const probe_table[] = { 329 { FE_DLCR2, 0x70, 0x00 }, 330 { FE_DLCR4, 0x08, 0x00 }, 331 { FE_DLCR5, 0x80, 0x00 }, 332 #if 0 333 { FE_BMPR16, 0x1B, 0x00 }, 334 { FE_BMPR17, 0x7F, 0x00 }, 335 #endif 336 { 0 } 337 }; 338 339 #if ATE_DEBUG >= 4 340 log(LOG_INFO, "ate_find: probe (0x%x) for ATI\n", iobase); 341 #if 0 342 fe_dump(LOG_INFO, sc); 343 #endif 344 #endif 345 346 /* 347 * We should test if MB86965A is on the base address now. 348 * Unfortunately, it is very hard to probe it reliably, since 349 * we have no way to reset the chip under software control. 350 * On cold boot, we could check the "signature" bit patterns 351 * described in the Fujitsu document. On warm boot, however, 352 * we can predict almost nothing about register values. 353 */ 354 if (!fe_simple_probe(iot, ioh, probe_table)) 355 return (0); 356 357 /* Check if our I/O address matches config info on 86965. */ 358 n = (bus_space_read_1(iot, ioh, FE_BMPR19) & FE_B19_ADDR) 359 >> FE_B19_ADDR_SHIFT; 360 *iobase = ate_iomap[n]; 361 362 /* 363 * We are now almost sure we have an AT1700 at the given 364 * address. So, read EEPROM through 86965. We have to write 365 * into LSI registers to read from EEPROM. I want to avoid it 366 * at this stage, but I cannot test the presense of the chip 367 * any further without reading EEPROM. FIXME. 368 */ 369 ate_read_eeprom(iot, ioh, eeprom); 370 371 /* Make sure that config info in EEPROM and 86965 agree. */ 372 if (eeprom[FE_EEPROM_CONF] != bus_space_read_1(iot, ioh, FE_BMPR19)) { 373 #ifdef DIAGNOSTIC 374 printf("ate_find: " 375 "incorrect configration in eeprom and chip\n"); 376 #endif 377 return (0); 378 } 379 380 /* 381 * Try to determine IRQ settings. 382 * Different models use different ranges of IRQs. 383 */ 384 n = (bus_space_read_1(iot, ioh, FE_BMPR19) & FE_B19_IRQ) 385 >> FE_B19_IRQ_SHIFT; 386 switch (eeprom[FE_ATI_EEP_REVISION] & 0xf0) { 387 case 0x30: 388 *irq = irqmap[3][n]; 389 break; 390 case 0x10: 391 case 0x50: 392 *irq = irqmap[2][n]; 393 break; 394 case 0x40: 395 case 0x60: 396 if (eeprom[FE_ATI_EEP_MAGIC] & 0x04) { 397 *irq = irqmap[1][n]; 398 break; 399 } 400 default: 401 *irq = irqmap[0][n]; 402 break; 403 } 404 405 return (1); 406 } 407 408 /* 409 * Determine type and ethernet address. 410 */ 411 static int 412 ate_detect(iot, ioh, enaddr) 413 bus_space_tag_t iot; 414 bus_space_handle_t ioh; 415 u_int8_t enaddr[ETHER_ADDR_LEN]; 416 { 417 u_char eeprom[FE_EEPROM_SIZE]; 418 int type; 419 420 /* Get our station address from EEPROM. */ 421 ate_read_eeprom(iot, ioh, eeprom); 422 bcopy(eeprom + FE_ATI_EEP_ADDR, enaddr, ETHER_ADDR_LEN); 423 424 /* Make sure we got a valid station address. */ 425 if ((enaddr[0] & 0x03) != 0x00 || 426 (enaddr[0] == 0x00 && enaddr[1] == 0x00 && enaddr[2] == 0x00)) { 427 #ifdef ATE_DEBUG 428 printf("fmv_detect: invalid ethernet address\n"); 429 #endif 430 return (0); 431 } 432 433 /* 434 * Determine the card type. 435 */ 436 switch (eeprom[FE_ATI_EEP_MODEL]) { 437 case FE_ATI_MODEL_AT1700T: 438 type = FE_TYPE_AT1700T; 439 break; 440 case FE_ATI_MODEL_AT1700BT: 441 type = FE_TYPE_AT1700BT; 442 break; 443 case FE_ATI_MODEL_AT1700FT: 444 type = FE_TYPE_AT1700FT; 445 break; 446 case FE_ATI_MODEL_AT1700AT: 447 type = FE_TYPE_AT1700AT; 448 break; 449 default: 450 type = FE_TYPE_RE2000; 451 break; 452 } 453 454 return (type); 455 } 456 457 void 458 ate_attach(parent, self, aux) 459 struct device *parent, *self; 460 void *aux; 461 { 462 struct ate_softc *isc = (struct ate_softc *)self; 463 struct mb86960_softc *sc = &isc->sc_mb86960; 464 struct isa_attach_args *ia = aux; 465 bus_space_tag_t iot = ia->ia_iot; 466 bus_space_handle_t ioh; 467 u_int8_t myea[ETHER_ADDR_LEN]; 468 const char *typestr; 469 int type; 470 471 printf("\n"); 472 473 /* Map i/o space. */ 474 if (bus_space_map(iot, ia->ia_iobase, ATE_NPORTS, 0, &ioh)) { 475 printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname); 476 return; 477 } 478 479 sc->sc_bst = iot; 480 sc->sc_bsh = ioh; 481 482 /* Determine the card type and get ehternet address. */ 483 type = ate_detect(iot, ioh, myea); 484 switch (type) { 485 case FE_TYPE_AT1700T: 486 typestr = "AT-1700T"; 487 break; 488 case FE_TYPE_AT1700BT: 489 typestr = "AT-1700BT"; 490 break; 491 case FE_TYPE_AT1700FT: 492 typestr = "AT-1700FT"; 493 break; 494 case FE_TYPE_AT1700AT: 495 typestr = "AT-1700AT"; 496 break; 497 case FE_TYPE_RE2000: 498 typestr = "unknown (RE-2000?)"; 499 break; 500 501 default: 502 /* Unknown card type: maybe a new model, but... */ 503 printf("%s: where did the card go?!\n", sc->sc_dev.dv_xname); 504 panic("unknown card"); 505 } 506 507 printf("%s: %s Ethernet\n", sc->sc_dev.dv_xname, typestr); 508 509 /* This interface is always enabled. */ 510 sc->sc_flags |= FE_FLAGS_ENABLED; 511 512 /* 513 * Do generic MB86960 attach. 514 */ 515 mb86960_attach(sc, MB86960_TYPE_86965, myea); 516 517 mb86960_config(sc, NULL, 0, 0); 518 519 /* Establish the interrupt handler. */ 520 isc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, 521 IPL_NET, mb86960_intr, sc); 522 if (isc->sc_ih == NULL) 523 printf("%s: couldn't establish interrupt handler\n", 524 sc->sc_dev.dv_xname); 525 } 526