1 1.20 msaitoh /* $NetBSD: if_ne_pbus.c,v 1.20 2019/05/29 06:21:56 msaitoh Exp $ */ 2 1.1 reinoud 3 1.1 reinoud /* 4 1.1 reinoud * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 1.1 reinoud * All rights reserved. 6 1.1 reinoud * 7 1.1 reinoud * This code is derived from software contributed to The NetBSD Foundation 8 1.1 reinoud * by Mark Brinicombe of Causality Limited. 9 1.1 reinoud * 10 1.1 reinoud * EtherH code Copyright (c) 1998 Mike Pumford 11 1.1 reinoud * EtherN/EtherI code Copyright (c) 1999 Mike Pumford 12 1.1 reinoud * 13 1.1 reinoud * Redistribution and use in source and binary forms, with or without 14 1.1 reinoud * modification, are permitted provided that the following conditions 15 1.1 reinoud * are met: 16 1.1 reinoud * 1. Redistributions of source code must retain the above copyright 17 1.1 reinoud * notice, this list of conditions and the following disclaimer. 18 1.1 reinoud * 2. Redistributions in binary form must reproduce the above copyright 19 1.1 reinoud * notice, this list of conditions and the following disclaimer in the 20 1.1 reinoud * documentation and/or other materials provided with the distribution. 21 1.1 reinoud * 22 1.1 reinoud * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23 1.1 reinoud * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 1.1 reinoud * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 1.1 reinoud * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26 1.1 reinoud * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 1.1 reinoud * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 1.1 reinoud * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 1.1 reinoud * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 1.1 reinoud * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 1.1 reinoud * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 1.1 reinoud * POSSIBILITY OF SUCH DAMAGE. 33 1.1 reinoud */ 34 1.1 reinoud 35 1.1 reinoud /* 36 1.1 reinoud * This driver uses the generic ne2000 & dp8390 IC drivers 37 1.1 reinoud * 38 1.1 reinoud * Currently supports: 39 1.1 reinoud * ANT EtherM network slot cards 40 1.1 reinoud * ICubed Etherlan 600 (EtherH) network slot cards 41 1.1 reinoud * Irlam EtherN podules 42 1.1 reinoud * Acorn EtherI podules (identical hardware to EtherN) 43 1.1 reinoud * 44 1.1 reinoud * Thanks go to Stephen Borrill for providing the EtherN card 45 1.1 reinoud * and information to program it. 46 1.1 reinoud * 47 1.1 reinoud * TO DO List for this Driver. 48 1.1 reinoud * 49 1.1 reinoud * EtherM - Needs proper media support. 50 1.1 reinoud */ 51 1.10 lukem 52 1.10 lukem #include <sys/cdefs.h> 53 1.20 msaitoh __KERNEL_RCSID(0, "$NetBSD: if_ne_pbus.c,v 1.20 2019/05/29 06:21:56 msaitoh Exp $"); 54 1.1 reinoud 55 1.1 reinoud #include <sys/param.h> 56 1.1 reinoud #include <sys/device.h> 57 1.1 reinoud #include <sys/socket.h> 58 1.1 reinoud #include <sys/systm.h> 59 1.1 reinoud #include <sys/mbuf.h> 60 1.16 dyoung #include <sys/bus.h> 61 1.1 reinoud 62 1.1 reinoud #include <net/if.h> 63 1.1 reinoud #include <net/if_dl.h> 64 1.1 reinoud #include <net/if_ether.h> 65 1.1 reinoud #include <net/if_media.h> 66 1.1 reinoud 67 1.2 thorpej #include <machine/intr.h> 68 1.1 reinoud #include <machine/io.h> 69 1.1 reinoud #include <dev/ic/dp8390reg.h> 70 1.1 reinoud #include <dev/ic/dp8390var.h> 71 1.1 reinoud #include <dev/ic/ne2000reg.h> 72 1.1 reinoud #include <dev/ic/ne2000var.h> 73 1.4 bjh21 #include <dev/ic/dp83905reg.h> 74 1.4 bjh21 #include <dev/ic/dp83905var.h> 75 1.3 bjh21 #include <dev/ic/mx98905var.h> 76 1.1 reinoud 77 1.1 reinoud #include <arch/acorn32/podulebus/podulebus.h> 78 1.1 reinoud #include <arch/acorn32/podulebus/if_ne_pbusreg.h> 79 1.1 reinoud 80 1.1 reinoud #include <dev/podulebus/podules.h> 81 1.1 reinoud 82 1.1 reinoud /* 83 1.1 reinoud * ne_pbus_softc: ne2000_softc plus podule, interrupt and bs tag info 84 1.1 reinoud */ 85 1.1 reinoud struct ne_pbus_softc { 86 1.1 reinoud struct ne2000_softc sc_ne2000; /* ne2000 softc */ 87 1.1 reinoud int sc_podule_number; 88 1.1 reinoud podule_t *sc_podule; 89 1.1 reinoud struct bus_space sc_tag; /* Patched tag */ 90 1.1 reinoud irqhandler_t *sc_ih; /* Interrupt handler */ 91 1.1 reinoud struct evcnt sc_intrcnt; /* Interrupt count */ 92 1.1 reinoud bus_space_handle_t sc_extrah; /* Bus handle for any 93 1.1 reinoud extra registers */ 94 1.1 reinoud }; 95 1.1 reinoud 96 1.1 reinoud /* 97 1.1 reinoud * Attach data and prototypes for driver 98 1.1 reinoud */ 99 1.14 cube static int ne_pbus_probe (device_t, cfdata_t , void *); 100 1.14 cube static void ne_pbus_attach (device_t, device_t, void *); 101 1.1 reinoud 102 1.14 cube CFATTACH_DECL_NEW(ne_pbus, sizeof(struct ne_pbus_softc), 103 1.9 thorpej ne_pbus_probe, ne_pbus_attach, NULL, NULL); 104 1.1 reinoud 105 1.1 reinoud /* 106 1.1 reinoud * Prototypes for interface specific routines 107 1.1 reinoud */ 108 1.17 skrll static uint8_t *em_ea (struct ne_pbus_softc *sc, uint8_t *buffer); 109 1.14 cube static void em_postattach (struct ne_pbus_softc *sc); 110 1.14 cube static void eh600_postattach (struct ne_pbus_softc *sc); 111 1.14 cube static void eh600_preattach (struct ne_pbus_softc *sc); 112 1.17 skrll static uint8_t *eh600_ea (struct ne_pbus_softc *sc, uint8_t *buffer); 113 1.1 reinoud 114 1.14 cube void eh600_init_media (struct dp8390_softc *); 115 1.1 reinoud 116 1.14 cube void en_postattach (struct ne_pbus_softc *); 117 1.14 cube void en_init_media (struct dp8390_softc *); 118 1.1 reinoud 119 1.1 reinoud /* 120 1.1 reinoud * Define a structure to hold all the information required on an NE2000 121 1.1 reinoud * clone interface. 122 1.1 reinoud * We create an array of these structures to describe all the interfaces 123 1.1 reinoud * that we can handle via the MI NE2000 driver. 124 1.1 reinoud */ 125 1.1 reinoud struct ne_clone { 126 1.1 reinoud int product; /* podule product id */ 127 1.1 reinoud unsigned int cookie; /* podulebus space cookie */ 128 1.1 reinoud unsigned int nicbase; /* byte offset of NIC */ 129 1.1 reinoud unsigned int nicsize; /* size of NIC (regs) */ 130 1.1 reinoud unsigned int asicbase; /* byte offset of ASIC */ 131 1.1 reinoud unsigned int asicsize; /* size of ASIC (regs) */ 132 1.1 reinoud unsigned int extrabase; /* extra registers byte offset */ 133 1.1 reinoud unsigned int extrasize; /* size of extra registers(regs) */ 134 1.1 reinoud unsigned char nicspace; /* easi,fast or mod space ? */ 135 1.1 reinoud unsigned char asicspace; /* easi,fast or mod space ? */ 136 1.1 reinoud unsigned char extraspace; /* easi,fast or mod space ? */ 137 1.1 reinoud #define NE_SPACE_FAST 0 138 1.1 reinoud #define NE_SPACE_MOD 1 139 1.1 reinoud #define NE_SPACE_EASI 2 140 1.1 reinoud unsigned char reserved0; /* not used (padding) */ 141 1.1 reinoud const char *name; /* name */ 142 1.17 skrll uint8_t * (*getea) /* do this to get the MAC */ 143 1.17 skrll (struct ne_pbus_softc *sc, uint8_t *buffer); 144 1.1 reinoud void (*preattach) /* do this before attach */ 145 1.14 cube (struct ne_pbus_softc *sc); 146 1.1 reinoud void (*postattach) /* do this after attach */ 147 1.14 cube (struct ne_pbus_softc *sc); 148 1.1 reinoud int (*mediachange) /* media change */ 149 1.14 cube (struct dp8390_softc *); 150 1.1 reinoud void (*mediastatus) /* media status */ 151 1.14 cube (struct dp8390_softc *, struct ifmediareq *); 152 1.1 reinoud void (*init_card) /* media init card */ 153 1.14 cube (struct dp8390_softc *); 154 1.1 reinoud void (*init_media) /* media init */ 155 1.14 cube (struct dp8390_softc *); 156 1.1 reinoud } ne_clones[] = { 157 1.1 reinoud /* ANT EtherM netslot interface */ 158 1.1 reinoud { 159 1.5 bjh21 PODULE_ETHERM, EM_REGSHIFT, 160 1.1 reinoud EM_NIC_OFFSET, EM_NIC_SIZE, EM_ASIC_OFFSET, EM_ASIC_SIZE, 161 1.1 reinoud 0,0, NE_SPACE_FAST, 162 1.1 reinoud NE_SPACE_FAST, NE_SPACE_FAST, 0, 163 1.1 reinoud "EtherM", em_ea, NULL, em_postattach, 164 1.1 reinoud NULL,NULL,NULL,NULL 165 1.1 reinoud }, 166 1.1 reinoud /* ICubed EtherLan EtherH netslot interface */ 167 1.1 reinoud { 168 1.5 bjh21 PODULE_ETHERLAN600, EH600_REGSHIFT, 169 1.1 reinoud EH600_NIC_OFFSET, EH600_NIC_SIZE, EH600_ASIC_OFFSET, EH600_ASIC_SIZE, 170 1.1 reinoud EH600_CONTROL_OFFSET, EH600_CONTROL_SIZE, NE_SPACE_FAST, 171 1.1 reinoud NE_SPACE_FAST, NE_SPACE_FAST, 0, 172 1.1 reinoud "EtherLan 600", eh600_ea, eh600_preattach, eh600_postattach, 173 1.4 bjh21 dp83905_mediachange, dp83905_mediastatus, dp83905_init_card, 174 1.1 reinoud eh600_init_media 175 1.1 reinoud }, 176 1.1 reinoud /* Acorn EtherLan EtherH netslot interface */ 177 1.1 reinoud { 178 1.5 bjh21 PODULE_ETHERLAN600AEH, EH600_REGSHIFT, 179 1.1 reinoud EH600_NIC_OFFSET, EH600_NIC_SIZE, EH600_ASIC_OFFSET, EH600_ASIC_SIZE, 180 1.1 reinoud EH600_CONTROL_OFFSET, EH600_CONTROL_SIZE, NE_SPACE_FAST, 181 1.1 reinoud NE_SPACE_FAST, NE_SPACE_FAST, 0, 182 1.1 reinoud "EtherLan 600A", eh600_ea , eh600_preattach, eh600_postattach, 183 1.4 bjh21 dp83905_mediachange, dp83905_mediastatus, dp83905_init_card, 184 1.1 reinoud eh600_init_media 185 1.1 reinoud }, 186 1.1 reinoud /* Irlam EtherN podule. (supplied with NC) */ 187 1.1 reinoud { 188 1.11 bjh21 PODULE_ETHERN, EN_REGSHIFT, 189 1.1 reinoud EN_NIC_OFFSET, EN_NIC_SIZE, EN_ASIC_OFFSET, EN_ASIC_SIZE, 190 1.1 reinoud 0,0, NE_SPACE_EASI, 191 1.1 reinoud NE_SPACE_EASI, NE_SPACE_EASI, 0, 192 1.3 bjh21 "EtherN", em_ea, NULL, en_postattach, 193 1.4 bjh21 dp83905_mediachange, dp83905_mediastatus, dp83905_init_card, 194 1.1 reinoud en_init_media 195 1.1 reinoud }, 196 1.1 reinoud /* Acorn EtherI podule. (supplied with NC) */ 197 1.1 reinoud { 198 1.12 bjh21 PODULE_ETHERI, EN_REGSHIFT, 199 1.1 reinoud EN_NIC_OFFSET, EN_NIC_SIZE, EN_ASIC_OFFSET, EN_ASIC_SIZE, 200 1.1 reinoud 0,0, NE_SPACE_EASI, 201 1.1 reinoud NE_SPACE_EASI, NE_SPACE_EASI, 0, 202 1.3 bjh21 "EtherI", em_ea, NULL, en_postattach, 203 1.4 bjh21 dp83905_mediachange, dp83905_mediastatus, dp83905_init_card, 204 1.1 reinoud en_init_media 205 1.1 reinoud }, 206 1.1 reinoud }; 207 1.1 reinoud 208 1.1 reinoud /* 209 1.1 reinoud * Determine if the device is present. 210 1.1 reinoud */ 211 1.1 reinoud static int 212 1.14 cube ne_pbus_probe(device_t parent, cfdata_t cf, void *aux) 213 1.1 reinoud { 214 1.19 msaitoh struct podule_attach_args *pa = (void *)aux; 215 1.1 reinoud int loop; 216 1.1 reinoud 217 1.1 reinoud /* Scan the list of known interfaces looking for a match */ 218 1.1 reinoud for (loop = 0; loop < sizeof(ne_clones) / sizeof(struct ne_clone); 219 1.1 reinoud ++loop) { 220 1.5 bjh21 if (pa->pa_product == ne_clones[loop].product) 221 1.19 msaitoh return 1; 222 1.1 reinoud } 223 1.19 msaitoh return 0; 224 1.1 reinoud } 225 1.1 reinoud 226 1.1 reinoud /* 227 1.1 reinoud * Install interface into kernel networking data structures. 228 1.1 reinoud */ 229 1.1 reinoud static void 230 1.14 cube ne_pbus_attach(device_t parent, device_t self, void *aux) 231 1.1 reinoud { 232 1.1 reinoud struct podule_attach_args *pa = (void *)aux; 233 1.14 cube struct ne_pbus_softc *npsc = device_private(self); 234 1.1 reinoud struct ne2000_softc *nsc = &npsc->sc_ne2000; 235 1.1 reinoud struct dp8390_softc *dsc = &nsc->sc_dp8390; 236 1.1 reinoud struct ne_clone *ne = NULL; 237 1.17 skrll uint8_t buffer[6]; 238 1.17 skrll uint8_t *myea; 239 1.1 reinoud int loop; 240 1.1 reinoud 241 1.14 cube dsc->sc_dev = self; 242 1.1 reinoud /* Check a few things about the attach args */ 243 1.1 reinoud 244 1.1 reinoud if (pa->pa_podule_number == -1) 245 1.1 reinoud panic("Podule has disappeared !"); 246 1.1 reinoud 247 1.1 reinoud npsc->sc_podule_number = pa->pa_podule_number; 248 1.1 reinoud npsc->sc_podule = pa->pa_podule; 249 1.1 reinoud podules[npsc->sc_podule_number].attached = 1; /* XXX */ 250 1.1 reinoud 251 1.1 reinoud /* Scan the list of known interfaces for a match */ 252 1.1 reinoud for (loop = 0; loop < sizeof(ne_clones) / sizeof(struct ne_clone); 253 1.1 reinoud ++loop) { 254 1.5 bjh21 if (pa->pa_product == ne_clones[loop].product) { 255 1.1 reinoud ne = &ne_clones[loop]; 256 1.1 reinoud break; 257 1.1 reinoud } 258 1.1 reinoud } 259 1.1 reinoud 260 1.1 reinoud #ifdef DIAGNOSTIC 261 1.1 reinoud /* This should never fail as we must have matched at probe time */ 262 1.1 reinoud if (ne == NULL) 263 1.6 provos panic("Podule has vanished"); 264 1.1 reinoud #endif 265 1.1 reinoud 266 1.1 reinoud /* Update the nic and asic base addresses appropriately */ 267 1.1 reinoud switch (ne->nicspace) { 268 1.1 reinoud case NE_SPACE_EASI: 269 1.1 reinoud ne->nicbase += npsc->sc_podule->easi_base; 270 1.1 reinoud break; 271 1.1 reinoud case NE_SPACE_MOD: 272 1.1 reinoud ne->nicbase += npsc->sc_podule->mod_base; 273 1.1 reinoud break; 274 1.1 reinoud case NE_SPACE_FAST: 275 1.1 reinoud default: 276 1.1 reinoud ne->nicbase += npsc->sc_podule->fast_base; 277 1.1 reinoud break; 278 1.1 reinoud } 279 1.1 reinoud switch (ne->asicspace) { 280 1.1 reinoud case NE_SPACE_EASI: 281 1.1 reinoud ne->asicbase += npsc->sc_podule->easi_base; 282 1.1 reinoud break; 283 1.1 reinoud case NE_SPACE_MOD: 284 1.1 reinoud ne->asicbase += npsc->sc_podule->mod_base; 285 1.1 reinoud break; 286 1.1 reinoud case NE_SPACE_FAST: 287 1.1 reinoud default: 288 1.1 reinoud ne->asicbase += npsc->sc_podule->fast_base; 289 1.1 reinoud break; 290 1.1 reinoud } 291 1.1 reinoud 292 1.1 reinoud switch (ne->extraspace) { 293 1.1 reinoud case NE_SPACE_EASI: 294 1.1 reinoud ne->extrabase += npsc->sc_podule->easi_base; 295 1.1 reinoud break; 296 1.1 reinoud case NE_SPACE_MOD: 297 1.1 reinoud ne->extrabase += npsc->sc_podule->mod_base; 298 1.1 reinoud break; 299 1.1 reinoud case NE_SPACE_FAST: 300 1.1 reinoud default: 301 1.1 reinoud ne->extrabase += npsc->sc_podule->fast_base; 302 1.1 reinoud break; 303 1.1 reinoud } 304 1.1 reinoud 305 1.1 reinoud /* Report the interface name */ 306 1.14 cube aprint_normal(": %s ethernet\n", ne->name); 307 1.1 reinoud 308 1.1 reinoud /* 309 1.1 reinoud * Ok we need our own bus tag as the register spacing 310 1.1 reinoud * may not the default. 311 1.1 reinoud * 312 1.1 reinoud * For the podulebus, the bus tag cookie is the shift 313 1.1 reinoud * to apply to registers 314 1.1 reinoud * So duplicate the bus space tag and change the 315 1.1 reinoud * cookie. 316 1.1 reinoud */ 317 1.1 reinoud 318 1.1 reinoud npsc->sc_tag = *pa->pa_iot; 319 1.1 reinoud npsc->sc_tag.bs_cookie = (void *) ne->cookie; 320 1.1 reinoud 321 1.1 reinoud dsc->sc_regt = &npsc->sc_tag; 322 1.1 reinoud nsc->sc_asict = dsc->sc_regt; 323 1.1 reinoud 324 1.1 reinoud /* Map all the I/O space for the NIC */ 325 1.1 reinoud if (bus_space_map(dsc->sc_regt, ne->nicbase, ne->nicsize, 326 1.1 reinoud 0, &dsc->sc_regh)) { 327 1.14 cube aprint_error_dev(self, "cannot map i/o space\n"); 328 1.1 reinoud return; 329 1.1 reinoud } 330 1.1 reinoud /* Map the I/O space for the ASIC */ 331 1.1 reinoud if (bus_space_map(nsc->sc_asict, ne->asicbase, ne->asicsize, 332 1.1 reinoud 0, &nsc->sc_asich)) { 333 1.14 cube aprint_error_dev(self, "cannot map i/o space\n"); 334 1.1 reinoud return; 335 1.1 reinoud } 336 1.1 reinoud /* Map any extra register space required by the card */ 337 1.1 reinoud if (ne->extrasize > 0) { 338 1.1 reinoud if (bus_space_map(&npsc->sc_tag, ne->extrabase, ne->extrasize, 339 1.1 reinoud 0, &npsc->sc_extrah)) { 340 1.14 cube aprint_error_dev(self, "cannot map extra space\n"); 341 1.1 reinoud return; 342 1.1 reinoud } 343 1.1 reinoud } 344 1.1 reinoud 345 1.1 reinoud /* This interface is always enabled. */ 346 1.1 reinoud dsc->sc_enabled = 1; 347 1.1 reinoud 348 1.1 reinoud /* 349 1.1 reinoud * Now get the ethernet address in an interface specific manner if 350 1.1 reinoud * specified 351 1.1 reinoud */ 352 1.1 reinoud if (ne->getea) 353 1.1 reinoud myea = ne->getea(npsc, buffer); 354 1.1 reinoud else 355 1.1 reinoud myea = NULL; 356 1.1 reinoud 357 1.1 reinoud /* Does the interface need a preattach call ? */ 358 1.1 reinoud if (ne->preattach) 359 1.1 reinoud ne->preattach(npsc); 360 1.1 reinoud 361 1.19 msaitoh /* If the interface has media support initialise it */ 362 1.1 reinoud if (ne->init_media) { 363 1.1 reinoud dsc->sc_mediachange = ne->mediachange; 364 1.1 reinoud dsc->sc_mediastatus = ne->mediastatus; 365 1.1 reinoud dsc->init_card = ne->init_card; 366 1.1 reinoud dsc->sc_media_init = ne->init_media; 367 1.18 christos #if 0 368 1.18 christos int *media = NULL, nmedia = 0, defmedia = 0; 369 1.18 christos ne->init_media(dsc, &media, &nmedia, &defmedia); 370 1.18 christos #endif 371 1.1 reinoud } 372 1.1 reinoud 373 1.1 reinoud /* 374 1.1 reinoud * Do generic NE2000 attach. This will read the station address 375 1.1 reinoud * from the EEPROM. 376 1.1 reinoud */ 377 1.1 reinoud ne2000_attach(nsc, myea); 378 1.14 cube aprint_normal_dev(self, ""); 379 1.1 reinoud switch (nsc->sc_type) { 380 1.1 reinoud case NE2000_TYPE_NE1000: 381 1.14 cube aprint_normal("NE1000"); 382 1.1 reinoud break; 383 1.1 reinoud case NE2000_TYPE_NE2000: 384 1.14 cube aprint_normal("NE2000"); 385 1.1 reinoud break; 386 1.1 reinoud case NE2000_TYPE_AX88190: 387 1.14 cube aprint_normal("AX88190"); 388 1.1 reinoud break; 389 1.1 reinoud case NE2000_TYPE_DL10019: 390 1.14 cube aprint_normal("DL10019"); 391 1.1 reinoud break; 392 1.19 msaitoh case NE2000_TYPE_DL10022: 393 1.14 cube aprint_normal("DL10022"); 394 1.1 reinoud break; 395 1.1 reinoud default: 396 1.1 reinoud printf("??"); 397 1.1 reinoud }; 398 1.14 cube aprint_normal(" chipset, %d Kb memory\n", dsc->mem_start/1024); 399 1.1 reinoud 400 1.1 reinoud /* Does the interface need a postattach call ? */ 401 1.1 reinoud if (ne->postattach) 402 1.1 reinoud ne->postattach(npsc); 403 1.1 reinoud 404 1.1 reinoud /* Install an interrupt handler */ 405 1.1 reinoud evcnt_attach_dynamic(&npsc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, 406 1.14 cube device_xname(self), "intr"); 407 1.1 reinoud npsc->sc_ih = podulebus_irq_establish(pa->pa_ih, IPL_NET, dp8390_intr, 408 1.1 reinoud dsc, &npsc->sc_intrcnt); 409 1.1 reinoud if (npsc->sc_ih == NULL) 410 1.1 reinoud panic("%s: Cannot install interrupt handler", 411 1.14 cube device_xname(self)); 412 1.19 msaitoh /* This feels wrong to do this here */ 413 1.1 reinoud npsc->sc_ih->ih_maskaddr = npsc->sc_podule->irq_addr; 414 1.1 reinoud npsc->sc_ih->ih_maskbits = npsc->sc_podule->irq_mask; 415 1.1 reinoud } 416 1.1 reinoud 417 1.1 reinoud /* 418 1.1 reinoud * em_ea() 419 1.1 reinoud * 420 1.1 reinoud * return the ethernet address for an EtherM netslot interface. 421 1.1 reinoud * The EtherM interface uses the machines ethernet address so just 422 1.1 reinoud * fill it out 423 1.1 reinoud */ 424 1.14 cube static uint8_t * 425 1.14 cube em_ea(struct ne_pbus_softc *sc, uint8_t *buffer) 426 1.1 reinoud { 427 1.1 reinoud /* 428 1.1 reinoud * Use the podulebus netslot_ea() function to get the netslot 429 1.1 reinoud * ethernet address. This is generated from the machine ID. 430 1.1 reinoud */ 431 1.1 reinoud 432 1.1 reinoud netslot_ea(buffer); 433 1.19 msaitoh return buffer; 434 1.1 reinoud } 435 1.1 reinoud 436 1.1 reinoud /* 437 1.1 reinoud * em_postattach() 438 1.1 reinoud * 439 1.1 reinoud * The EtherM interface has a Diagnostic Status register. After attaching 440 1.1 reinoud * the driver, print out some more information using this register. 441 1.1 reinoud */ 442 1.1 reinoud static void 443 1.14 cube em_postattach(struct ne_pbus_softc *sc) 444 1.1 reinoud { 445 1.1 reinoud int dsr; 446 1.1 reinoud 447 1.1 reinoud /* 448 1.1 reinoud * Report information from the Diagnostic Status Register for 449 1.1 reinoud * the EtherM card 450 1.1 reinoud */ 451 1.14 cube aprint_normal_dev(sc->sc_ne2000.sc_dp8390.sc_dev, 452 1.14 cube "16KB buffer memory"); 453 1.1 reinoud 454 1.1 reinoud /* Get the Diagnostic Status Register */ 455 1.1 reinoud dsr = bus_space_read_1(sc->sc_ne2000.sc_asict, 456 1.1 reinoud sc->sc_ne2000.sc_asich, EM_DSR_REG); 457 1.1 reinoud 458 1.1 reinoud /* Check for bits that indicate a fault */ 459 1.1 reinoud if (!(dsr & EM_DSR_20M)) 460 1.14 cube aprint_normal(", VCO faulty"); 461 1.1 reinoud if (!(dsr & EM_DSR_TCOK)) 462 1.14 cube aprint_normal(", TxClk faulty"); 463 1.1 reinoud 464 1.1 reinoud /* Report status of card */ 465 1.1 reinoud if (dsr & EM_DSR_POL) 466 1.14 cube aprint_normal(", UTP reverse polarity"); 467 1.1 reinoud if (dsr & EM_DSR_JAB) 468 1.14 cube aprint_normal(", jabber"); 469 1.1 reinoud if (dsr & EM_DSR_LNK) 470 1.14 cube aprint_normal(", link OK"); 471 1.1 reinoud if (dsr & EM_DSR_LBK) 472 1.14 cube aprint_normal(", loopback"); 473 1.1 reinoud if (dsr & EM_DSR_UTP) 474 1.14 cube aprint_normal(", UTP"); 475 1.14 cube aprint_normal("\n"); 476 1.1 reinoud } 477 1.1 reinoud 478 1.1 reinoud 479 1.1 reinoud /* 480 1.1 reinoud * eh600_preattach() 481 1.1 reinoud * 482 1.19 msaitoh * pre-initialise the AT/Lantic chipset so that the card probes and 483 1.19 msaitoh * detects properly. 484 1.1 reinoud */ 485 1.1 reinoud static void 486 1.14 cube eh600_preattach(struct ne_pbus_softc *sc) 487 1.1 reinoud { 488 1.1 reinoud u_char tmp; 489 1.1 reinoud struct ne2000_softc *nsc = &sc->sc_ne2000; 490 1.1 reinoud struct dp8390_softc *dsc = &nsc->sc_dp8390; 491 1.1 reinoud bus_space_tag_t nict = dsc->sc_regt; 492 1.1 reinoud bus_space_handle_t nich = dsc->sc_regh; 493 1.19 msaitoh 494 1.19 msaitoh /* Initialise EH600 config register */ 495 1.4 bjh21 bus_space_read_1(nict, nich, DP83905_MCRA); 496 1.4 bjh21 bus_space_write_1(nict, nich, DP83905_MCRA, DP83905_MCRA_INT3); 497 1.1 reinoud 498 1.19 msaitoh /* Enable interrupts for the card */ 499 1.20 msaitoh tmp = bus_space_read_1(&sc->sc_tag, sc->sc_extrah, 0); 500 1.1 reinoud tmp |= EH_INTR_MASK; 501 1.20 msaitoh bus_space_write_1(&sc->sc_tag, sc->sc_extrah, 0, tmp); 502 1.1 reinoud } 503 1.1 reinoud 504 1.1 reinoud /* 505 1.1 reinoud * eh600_postattach() 506 1.1 reinoud * 507 1.19 msaitoh * Etherlan 600 has 32k of buffer memory as it runs the AT/Lantic 508 1.19 msaitoh * DP8390 clone in IO non-compatible mode. We need to adjust the memory 509 1.1 reinoud * description set up by dp8390.c and ne2000.c to reflect this. 510 1.1 reinoud */ 511 1.1 reinoud static void 512 1.14 cube eh600_postattach(struct ne_pbus_softc *sc) 513 1.1 reinoud { 514 1.1 reinoud struct ne2000_softc *nsc = &sc->sc_ne2000; 515 1.1 reinoud struct dp8390_softc *dsc = &nsc->sc_dp8390; 516 1.19 msaitoh 517 1.19 msaitoh /* First page is mapped to the PROM. so start at 2nd page */ 518 1.1 reinoud dsc->mem_start = EH600_MEM_START; 519 1.1 reinoud dsc->mem_size = EH600_MEM_END - EH600_MEM_START; 520 1.1 reinoud dsc->mem_end = EH600_MEM_END; 521 1.1 reinoud dsc->txb_cnt = 3; /* >16k of ram setup 3 tx buffers */ 522 1.19 msaitoh /* Recompute the mem ring (taken straight from the ne2000 init code) */ 523 1.19 msaitoh dsc->mem_ring = 524 1.19 msaitoh dsc->mem_start + 525 1.1 reinoud (((dsc->txb_cnt + 1) * ED_TXBUF_SIZE ) << 526 1.1 reinoud ED_PAGE_SHIFT); 527 1.1 reinoud 528 1.19 msaitoh /* Recompute the dp8390 register values. (from dp8390 init code) */ 529 1.1 reinoud dsc->tx_page_start = dsc->mem_start >> ED_PAGE_SHIFT; 530 1.1 reinoud 531 1.19 msaitoh dsc->rec_page_start = dsc->tx_page_start + 532 1.1 reinoud (dsc->txb_cnt + 1) * ED_TXBUF_SIZE; 533 1.1 reinoud 534 1.19 msaitoh dsc->rec_page_stop = dsc->tx_page_start + 535 1.1 reinoud (dsc->mem_size >> ED_PAGE_SHIFT); 536 1.14 cube aprint_normal_dev(dsc->sc_dev, "32KB buffer memory\n"); 537 1.1 reinoud } 538 1.1 reinoud /* 539 1.1 reinoud * EtherLan 600 media. 540 1.1 reinoud */ 541 1.14 cube void eh600_init_media(struct dp8390_softc *sc) 542 1.1 reinoud { 543 1.1 reinoud static int eh600_media[] = { 544 1.19 msaitoh IFM_ETHER | IFM_AUTO, 545 1.19 msaitoh IFM_ETHER | IFM_10_T, 546 1.19 msaitoh IFM_ETHER | IFM_10_2, 547 1.1 reinoud }; 548 1.19 msaitoh int i, defmedia = IFM_ETHER | IFM_AUTO; 549 1.19 msaitoh static const int eh600_nmedia = __arraycount(eh600_media); 550 1.1 reinoud 551 1.14 cube aprint_normal_dev(sc->sc_dev, 552 1.14 cube "10base2, 10baseT, auto, default auto\n"); 553 1.1 reinoud 554 1.1 reinoud ifmedia_init(&sc->sc_media, 0, dp8390_mediachange, dp8390_mediastatus); 555 1.1 reinoud for (i = 0; i < eh600_nmedia; i++) 556 1.1 reinoud ifmedia_add(&sc->sc_media, eh600_media[i], 0, NULL); 557 1.1 reinoud ifmedia_set(&sc->sc_media, defmedia); 558 1.1 reinoud } 559 1.1 reinoud 560 1.1 reinoud 561 1.3 bjh21 void 562 1.14 cube en_postattach(struct ne_pbus_softc *sc) 563 1.3 bjh21 { 564 1.3 bjh21 565 1.3 bjh21 mx98905_attach(&sc->sc_ne2000.sc_dp8390); 566 1.3 bjh21 } 567 1.1 reinoud 568 1.1 reinoud /* 569 1.1 reinoud * EtherN media. 570 1.1 reinoud */ 571 1.1 reinoud void 572 1.14 cube en_init_media(struct dp8390_softc *sc) 573 1.1 reinoud { 574 1.1 reinoud static int en_media[] = { 575 1.20 msaitoh IFM_ETHER | IFM_10_T 576 1.1 reinoud }; 577 1.19 msaitoh 578 1.14 cube aprint_normal_dev(sc->sc_dev, "10baseT, default 10baseT\n"); 579 1.1 reinoud 580 1.1 reinoud ifmedia_init(&sc->sc_media, 0, dp8390_mediachange, dp8390_mediastatus); 581 1.1 reinoud ifmedia_add(&sc->sc_media, en_media[0], 0, NULL); 582 1.1 reinoud ifmedia_set(&sc->sc_media, en_media[0]); 583 1.1 reinoud } 584 1.1 reinoud 585 1.1 reinoud 586 1.19 msaitoh /* 587 1.1 reinoud * extracts the station address from the Podule description string. 588 1.19 msaitoh * The description has to be re-read here since the podule description 589 1.1 reinoud * string is not always long enough to contain the full address. 590 1.1 reinoud * 591 1.19 msaitoh * If for any reason we cannot extract the address this routine will 592 1.1 reinoud * use netslot_ea() to return the generic address for the network slot. 593 1.1 reinoud */ 594 1.1 reinoud 595 1.1 reinoud #define POD_READ(addr) \ 596 1.1 reinoud podule->read_rom(podule->sync_base, addr) 597 1.1 reinoud 598 1.14 cube static uint8_t * 599 1.14 cube eh600_ea(struct ne_pbus_softc *sc, uint8_t *buffer) 600 1.1 reinoud { 601 1.1 reinoud podule_t *podule = sc->sc_podule; 602 1.1 reinoud u_int address; 603 1.1 reinoud u_int id; 604 1.1 reinoud 605 1.1 reinoud address = 0x40; 606 1.1 reinoud memset(buffer, 0, 6); 607 1.1 reinoud 608 1.19 msaitoh /* Read chunks from the podule */ 609 1.1 reinoud do { 610 1.1 reinoud id = POD_READ(address); 611 1.19 msaitoh /* Check for description chunk. */ 612 1.1 reinoud if (id == 0xf5) { 613 1.1 reinoud u_int size; 614 1.1 reinoud u_int pod_addr; 615 1.1 reinoud int loop; 616 1.1 reinoud 617 1.19 msaitoh /* Read the size */ 618 1.1 reinoud size = POD_READ(address + 4); 619 1.1 reinoud size |= (POD_READ(address + 8) << 8); 620 1.1 reinoud size |= (POD_READ(address + 12) << 16); 621 1.1 reinoud 622 1.19 msaitoh /* Read address of description */ 623 1.1 reinoud pod_addr = POD_READ(address + 16); 624 1.1 reinoud pod_addr |= (POD_READ(address + 20) << 8); 625 1.1 reinoud pod_addr |= (POD_READ(address + 24) << 16); 626 1.1 reinoud pod_addr |= (POD_READ(address + 28) << 24); 627 1.1 reinoud 628 1.1 reinoud if (pod_addr < 0x800) { 629 1.17 skrll uint8_t tmp; 630 1.1 reinoud int addr_index = 0; 631 1.1 reinoud int found_ether = 0; 632 1.1 reinoud 633 1.1 reinoud /* 634 1.19 msaitoh * Start scanning for ethernet address 635 1.1 reinoud * which starts with a '(' 636 1.1 reinoud */ 637 1.1 reinoud for (loop = 0; loop < size; ++loop) { 638 1.1 reinoud if (found_ether) { 639 1.19 msaitoh /* We have found a '(' so start decoding the address */ 640 1.1 reinoud tmp = POD_READ((pod_addr + loop) * 4); 641 1.1 reinoud if (tmp >= '0' && tmp <= '9') { 642 1.1 reinoud buffer[addr_index >> 1] |= (tmp - '0') << ((addr_index & 1) ? 0 : 4); 643 1.1 reinoud ++addr_index; 644 1.1 reinoud } 645 1.19 msaitoh else if (tmp >= 'a' && tmp <= 'f'){ 646 1.1 reinoud buffer[addr_index >> 1] |= (10 + (tmp - 'a')) << ((addr_index & 1) ? 0 : 4); 647 1.1 reinoud ++addr_index; 648 1.1 reinoud } 649 1.19 msaitoh else if (tmp >= 'A' && tmp <= 'F'){ 650 1.1 reinoud buffer[addr_index >> 1] |= (10 + (tmp - 'A')) << ((addr_index & 1) ? 0 : 4); 651 1.1 reinoud ++addr_index; 652 1.1 reinoud } 653 1.1 reinoud else if (tmp == ')') { 654 1.19 msaitoh /* We have read the whole address so we can stop scanning 655 1.1 reinoud * the podule description */ 656 1.1 reinoud break; 657 1.1 reinoud } 658 1.1 reinoud } 659 1.1 reinoud /* 660 1.19 msaitoh * We have found the start of the ethernet address (decode begins 661 1.1 reinoud * on the next run round the loop. */ 662 1.1 reinoud if (POD_READ((pod_addr + loop) * 4) == '(') { 663 1.1 reinoud found_ether = 1; 664 1.1 reinoud } 665 1.1 reinoud } 666 1.1 reinoud /* 667 1.1 reinoud * Failed to find the address so fall back 668 1.1 reinoud * on the netslot address 669 1.1 reinoud */ 670 1.1 reinoud if (!found_ether) 671 1.1 reinoud netslot_ea(buffer); 672 1.19 msaitoh return buffer; 673 1.1 reinoud } 674 1.1 reinoud } 675 1.1 reinoud address += 32; 676 1.1 reinoud } while (id != 0 && address < 0x8000); 677 1.1 reinoud 678 1.1 reinoud /* 679 1.1 reinoud * If we get here we failed to find the address 680 1.1 reinoud * In this case the best solution is to go with the netslot addrness 681 1.1 reinoud */ 682 1.1 reinoud netslot_ea(buffer); 683 1.19 msaitoh return buffer; 684 1.1 reinoud } 685