1 /* $NetBSD: if_we_pnpbus.c,v 1.2 2007/10/17 19:56:52 garbled Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Device driver for National Semiconductor DS8390/WD83C690 based ethernet 42 * adapters. 43 * 44 * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. 45 * 46 * Copyright (C) 1993, David Greenman. This software may be used, modified, 47 * copied, distributed, and sold, in both source and binary form provided that 48 * the above copyright and these terms are retained. Under no circumstances is 49 * the author responsible for the proper functioning of this software, nor does 50 * the author assume any responsibility for damages incurred with its use. 51 */ 52 53 /* 54 * Device driver for the Western Digital/SMC 8003 and 8013 series, 55 * and the SMC Elite Ultra (8216). 56 */ 57 58 #include <sys/cdefs.h> 59 __KERNEL_RCSID(0, "$NetBSD: if_we_pnpbus.c,v 1.2 2007/10/17 19:56:52 garbled Exp $"); 60 61 #include <sys/types.h> 62 #include <sys/param.h> 63 #include <sys/systm.h> 64 #include <sys/device.h> 65 #include <sys/socket.h> 66 #include <sys/mbuf.h> 67 #include <sys/syslog.h> 68 #include <sys/bswap.h> 69 70 #include <net/if.h> 71 #include <net/if_dl.h> 72 #include <net/if_types.h> 73 #include <net/if_media.h> 74 75 #include <net/if_ether.h> 76 77 #include <machine/bus.h> 78 #include <machine/intr.h> 79 #include <machine/isa_machdep.h> 80 #include <machine/residual.h> 81 82 #include <dev/ic/dp8390reg.h> 83 #include <dev/ic/dp8390var.h> 84 #include <dev/ic/wereg.h> 85 #include <dev/ic/wevar.h> 86 87 #include <prep/pnpbus/pnpbusvar.h> 88 89 int we_pnpbus_probe(struct device *, struct cfdata *, void *); 90 void we_pnpbus_attach(struct device *, struct device *, void *); 91 92 CFATTACH_DECL(we_pnpbus, sizeof(struct we_softc), 93 we_pnpbus_probe, we_pnpbus_attach, NULL, NULL); 94 95 extern struct cfdriver we_cd; 96 97 static const char *we_params(bus_space_tag_t, bus_space_handle_t, 98 u_int8_t *, bus_size_t *, u_int8_t *, int *); 99 100 #define WE_DEFAULT_IOMEM 0xe4000 101 102 /* 103 * Delay needed when switching 16-bit access to shared memory. 104 */ 105 #define WE_DELAY(wsc) delay(3) 106 107 /* 108 * Enable card RAM, and 16-bit access. 109 */ 110 #define WE_MEM_ENABLE(wsc) \ 111 do { \ 112 if ((wsc)->sc_16bitp) \ 113 bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \ 114 WE_LAAR, (wsc)->sc_laar_proto | WE_LAAR_M16EN); \ 115 bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \ 116 WE_MSR, wsc->sc_msr_proto | WE_MSR_MENB); \ 117 WE_DELAY((wsc)); \ 118 } while (0) 119 120 /* 121 * Disable card RAM, and 16-bit access. 122 */ 123 #define WE_MEM_DISABLE(wsc) \ 124 do { \ 125 bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \ 126 WE_MSR, (wsc)->sc_msr_proto); \ 127 if ((wsc)->sc_16bitp) \ 128 bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \ 129 WE_LAAR, (wsc)->sc_laar_proto); \ 130 WE_DELAY((wsc)); \ 131 } while (0) 132 133 int 134 we_pnpbus_probe(struct device *parent, struct cfdata *cf, void *aux) 135 { 136 struct pnpbus_dev_attach_args *pna = aux; 137 int ret = 0; 138 139 if (strcmp(pna->pna_devid, "IBM2001") == 0) 140 ret = 1; 141 142 if (strcmp(pna->pna_devid, "IBM0010") == 0) 143 ret = 1; 144 145 if (ret) 146 pnpbus_scan(pna, pna->pna_ppc_dev); 147 148 return ret; 149 } 150 151 void 152 we_pnpbus_attach(struct device *parent, struct device *self, void *aux) 153 { 154 struct we_softc *wsc = (struct we_softc *)self; 155 struct dp8390_softc *sc = &wsc->sc_dp8390; 156 struct pnpbus_dev_attach_args *pna = aux; 157 struct pnpbus_irq *irq; 158 bus_space_tag_t nict, asict, memt; 159 bus_space_handle_t nich, asich, memh; 160 bus_size_t memsize = 0x4000; 161 const char *typestr; 162 int memfound = 0, i, irqnum; 163 164 nict = asict = pna->pna_iot; 165 memt = pna->pna_memt; 166 167 aprint_normal("\n"); 168 169 if (pnpbus_io_map(&pna->pna_res, 0, &asict, &asich)) { 170 aprint_error("%s: can't map nic i/o space\n", 171 device_xname(self)); 172 return; 173 } 174 175 if (bus_space_subregion(asict, asich, WE_NIC_OFFSET, WE_NIC_NPORTS, 176 &nich)) { 177 aprint_error("%s: can't subregion i/o space\n", 178 device_xname(self)); 179 return; 180 } 181 182 typestr = we_params(asict, asich, &wsc->sc_type, &memsize, 183 &wsc->sc_flags, &sc->is790); 184 if (typestr == NULL) { 185 aprint_error("%s: where did the card go?\n", 186 device_xname(self)); 187 return; 188 } 189 190 /* 191 * Map memory space. See if any was allocated via PNP, if not, use 192 * the default. 193 */ 194 if (pnpbus_iomem_map(&pna->pna_res, 0, &memt, &memh) == 0) 195 memfound = 1; 196 else if (bus_space_map(memt, WE_DEFAULT_IOMEM, memsize, 0, &memh)) { 197 aprint_error("%s: can't map shared memory\n", 198 device_xname(self)); 199 return; 200 } 201 202 wsc->sc_asict = asict; 203 wsc->sc_asich = asich; 204 205 sc->sc_regt = nict; 206 sc->sc_regh = nich; 207 208 sc->sc_buft = memt; 209 sc->sc_bufh = memh; 210 211 if (memfound) 212 pnpbus_getiomem(&pna->pna_res, 0, &wsc->sc_maddr, 213 &sc->mem_size); 214 else { 215 wsc->sc_maddr = WE_DEFAULT_IOMEM; 216 sc->mem_size = memsize; 217 } 218 219 /* Interface is always enabled. */ 220 sc->sc_enabled = 1; 221 222 if (we_config(self, wsc, typestr)) 223 return; 224 225 /* 226 * Enable the configured interrupt. 227 */ 228 #if 0 229 if (sc->is790) 230 bus_space_write_1(asict, asich, WE790_ICR, 231 bus_space_read_1(asict, asich, WE790_ICR) | 232 WE790_ICR_EIL); 233 else if (wsc->sc_type & WE_SOFTCONFIG) 234 bus_space_write_1(asict, asich, WE_IRR, 235 bus_space_read_1(asict, asich, WE_IRR) | WE_IRR_IEN); 236 #endif 237 238 /* 239 * Establish interrupt handler. 240 * Loop through all probed IRQs until one looks sane. 241 */ 242 for (i = 0, irq = SIMPLEQ_FIRST(&pna->pna_res.irq); 243 i < pna->pna_res.numirq; i++, irq = SIMPLEQ_NEXT(irq, next)) { 244 irqnum = ffs(irq->mask) - 1; 245 /* some cards think they are level. force them to edge */ 246 if (irq->flags & 0x0c) 247 irq->flags = 0x01; 248 if (!LEGAL_IRQ(irqnum)) 249 continue; 250 if (irqnum < 2) 251 continue; 252 break; 253 } 254 wsc->sc_ih = pnpbus_intr_establish(i, IPL_NET, dp8390_intr, sc, 255 &pna->pna_res); 256 if (wsc->sc_ih == NULL) 257 aprint_error("%s: can't establish interrupt\n", 258 device_xname(self)); 259 } 260 261 static const char * 262 we_params(asict, asich, typep, memsizep, flagp, is790p) 263 bus_space_tag_t asict; 264 bus_space_handle_t asich; 265 u_int8_t *typep, *flagp; 266 bus_size_t *memsizep; 267 int *is790p; 268 { 269 const char *typestr; 270 bus_size_t memsize; 271 int is16bit, is790; 272 u_int8_t type; 273 274 memsize = 8192; 275 is16bit = is790 = 0; 276 277 type = bus_space_read_1(asict, asich, WE_CARD_ID); 278 switch (type) { 279 case WE_TYPE_WD8003S: 280 typestr = "WD8003S"; 281 break; 282 case WE_TYPE_WD8003E: 283 typestr = "WD8003E"; 284 break; 285 case WE_TYPE_WD8003EB: 286 typestr = "WD8003EB"; 287 break; 288 case WE_TYPE_WD8003W: 289 typestr = "WD8003W"; 290 break; 291 case WE_TYPE_WD8013EBT: 292 typestr = "WD8013EBT"; 293 memsize = 16384; 294 is16bit = 1; 295 break; 296 case WE_TYPE_WD8013W: 297 typestr = "WD8013W"; 298 memsize = 16384; 299 is16bit = 1; 300 break; 301 case WE_TYPE_WD8013EP: /* also WD8003EP */ 302 if (bus_space_read_1(asict, asich, WE_ICR) & WE_ICR_16BIT) { 303 is16bit = 1; 304 memsize = 16384; 305 typestr = "WD8013EP"; 306 } else 307 typestr = "WD8003EP"; 308 break; 309 case WE_TYPE_WD8013WC: 310 typestr = "WD8013WC"; 311 memsize = 16384; 312 is16bit = 1; 313 break; 314 case WE_TYPE_WD8013EBP: 315 typestr = "WD8013EBP"; 316 memsize = 16384; 317 is16bit = 1; 318 break; 319 case WE_TYPE_WD8013EPC: 320 typestr = "WD8013EPC"; 321 memsize = 16384; 322 is16bit = 1; 323 break; 324 case WE_TYPE_SMC8216C: 325 case WE_TYPE_SMC8216T: 326 { 327 u_int8_t hwr; 328 329 typestr = (type == WE_TYPE_SMC8216C) ? 330 "SMC8216/SMC8216C" : "SMC8216T"; 331 332 hwr = bus_space_read_1(asict, asich, WE790_HWR); 333 bus_space_write_1(asict, asich, WE790_HWR, 334 hwr | WE790_HWR_SWH); 335 switch (bus_space_read_1(asict, asich, WE790_RAR) & 336 WE790_RAR_SZ64) { 337 case WE790_RAR_SZ64: 338 memsize = 65536; 339 break; 340 case WE790_RAR_SZ32: 341 memsize = 32768; 342 break; 343 case WE790_RAR_SZ16: 344 memsize = 16384; 345 break; 346 case WE790_RAR_SZ8: 347 /* 8216 has 16K shared mem -- 8416 has 8K */ 348 typestr = (type == WE_TYPE_SMC8216C) ? 349 "SMC8416C/SMC8416BT" : "SMC8416T"; 350 memsize = 8192; 351 break; 352 } 353 bus_space_write_1(asict, asich, WE790_HWR, hwr); 354 355 is16bit = 1; 356 is790 = 1; 357 break; 358 } 359 #ifdef TOSH_ETHER 360 case WE_TYPE_TOSHIBA1: 361 typestr = "Toshiba1"; 362 memsize = 32768; 363 is16bit = 1; 364 break; 365 case WE_TYPE_TOSHIBA4: 366 typestr = "Toshiba4"; 367 memsize = 32768; 368 is16bit = 1; 369 break; 370 #endif 371 default: 372 /* Not one we recognize. */ 373 return (NULL); 374 } 375 376 /* 377 * Make some adjustments to initial values depending on what is 378 * found in the ICR. 379 */ 380 if (is16bit && (type != WE_TYPE_WD8013EBT) && 381 #ifdef TOSH_ETHER 382 (type != WE_TYPE_TOSHIBA1 && type != WE_TYPE_TOSHIBA4) && 383 #endif 384 (bus_space_read_1(asict, asich, WE_ICR) & WE_ICR_16BIT) == 0) { 385 is16bit = 0; 386 memsize = 8192; 387 } 388 389 #ifdef WE_DEBUG 390 { 391 int i; 392 393 aprint_debug("we_params: type = 0x%x, typestr = %s," 394 " is16bit = %d, memsize = %d\n", type, typestr, is16bit, 395 memsize); 396 for (i = 0; i < 8; i++) 397 aprint_debug(" %d -> 0x%x\n", i, 398 bus_space_read_1(asict, asich, i)); 399 } 400 #endif 401 402 if (typep != NULL) 403 *typep = type; 404 if (memsizep != NULL) 405 *memsizep = memsize; 406 if (flagp != NULL && is16bit) 407 *flagp |= WE_16BIT_ENABLE; 408 if (is790p != NULL) 409 *is790p = is790; 410 return (typestr); 411 } 412