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