1 /* $NetBSD: if_we_pnpbus.c,v 1.8 2011/07/01 16:55:42 dyoung 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.8 2011/07/01 16:55:42 dyoung 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 <sys/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(device_t, cfdata_t, void *); 83 void we_pnpbus_attach(device_t, device_t, 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(device_t parent, cfdata_t 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(device_t parent, device_t self, void *aux) 146 { 147 struct we_softc *wsc = device_private(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_HWIRQ_P(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(bus_space_tag_t asict, bus_space_handle_t asich, u_int8_t *typep, bus_size_t *memsizep, u_int8_t *flagp, int *is790p) 256 { 257 const char *typestr; 258 bus_size_t memsize; 259 int is16bit, is790; 260 u_int8_t type; 261 262 memsize = 8192; 263 is16bit = is790 = 0; 264 265 type = bus_space_read_1(asict, asich, WE_CARD_ID); 266 switch (type) { 267 case WE_TYPE_WD8003S: 268 typestr = "WD8003S"; 269 break; 270 case WE_TYPE_WD8003E: 271 typestr = "WD8003E"; 272 break; 273 case WE_TYPE_WD8003EB: 274 typestr = "WD8003EB"; 275 break; 276 case WE_TYPE_WD8003W: 277 typestr = "WD8003W"; 278 break; 279 case WE_TYPE_WD8013EBT: 280 typestr = "WD8013EBT"; 281 memsize = 16384; 282 is16bit = 1; 283 break; 284 case WE_TYPE_WD8013W: 285 typestr = "WD8013W"; 286 memsize = 16384; 287 is16bit = 1; 288 break; 289 case WE_TYPE_WD8013EP: /* also WD8003EP */ 290 if (bus_space_read_1(asict, asich, WE_ICR) & WE_ICR_16BIT) { 291 is16bit = 1; 292 memsize = 16384; 293 typestr = "WD8013EP"; 294 } else 295 typestr = "WD8003EP"; 296 break; 297 case WE_TYPE_WD8013WC: 298 typestr = "WD8013WC"; 299 memsize = 16384; 300 is16bit = 1; 301 break; 302 case WE_TYPE_WD8013EBP: 303 typestr = "WD8013EBP"; 304 memsize = 16384; 305 is16bit = 1; 306 break; 307 case WE_TYPE_WD8013EPC: 308 typestr = "WD8013EPC"; 309 memsize = 16384; 310 is16bit = 1; 311 break; 312 case WE_TYPE_SMC8216C: 313 case WE_TYPE_SMC8216T: 314 { 315 u_int8_t hwr; 316 317 typestr = (type == WE_TYPE_SMC8216C) ? 318 "SMC8216/SMC8216C" : "SMC8216T"; 319 320 hwr = bus_space_read_1(asict, asich, WE790_HWR); 321 bus_space_write_1(asict, asich, WE790_HWR, 322 hwr | WE790_HWR_SWH); 323 switch (bus_space_read_1(asict, asich, WE790_RAR) & 324 WE790_RAR_SZ64) { 325 case WE790_RAR_SZ64: 326 memsize = 65536; 327 break; 328 case WE790_RAR_SZ32: 329 memsize = 32768; 330 break; 331 case WE790_RAR_SZ16: 332 memsize = 16384; 333 break; 334 case WE790_RAR_SZ8: 335 /* 8216 has 16K shared mem -- 8416 has 8K */ 336 typestr = (type == WE_TYPE_SMC8216C) ? 337 "SMC8416C/SMC8416BT" : "SMC8416T"; 338 memsize = 8192; 339 break; 340 } 341 bus_space_write_1(asict, asich, WE790_HWR, hwr); 342 343 is16bit = 1; 344 is790 = 1; 345 break; 346 } 347 #ifdef TOSH_ETHER 348 case WE_TYPE_TOSHIBA1: 349 typestr = "Toshiba1"; 350 memsize = 32768; 351 is16bit = 1; 352 break; 353 case WE_TYPE_TOSHIBA4: 354 typestr = "Toshiba4"; 355 memsize = 32768; 356 is16bit = 1; 357 break; 358 #endif 359 default: 360 /* Not one we recognize. */ 361 return (NULL); 362 } 363 364 /* 365 * Make some adjustments to initial values depending on what is 366 * found in the ICR. 367 */ 368 if (is16bit && (type != WE_TYPE_WD8013EBT) && 369 #ifdef TOSH_ETHER 370 (type != WE_TYPE_TOSHIBA1 && type != WE_TYPE_TOSHIBA4) && 371 #endif 372 (bus_space_read_1(asict, asich, WE_ICR) & WE_ICR_16BIT) == 0) { 373 is16bit = 0; 374 memsize = 8192; 375 } 376 377 #ifdef WE_DEBUG 378 { 379 int i; 380 381 aprint_debug("we_params: type = 0x%x, typestr = %s," 382 " is16bit = %d, memsize = %d\n", type, typestr, is16bit, 383 memsize); 384 for (i = 0; i < 8; i++) 385 aprint_debug(" %d -> 0x%x\n", i, 386 bus_space_read_1(asict, asich, i)); 387 } 388 #endif 389 390 if (typep != NULL) 391 *typep = type; 392 if (memsizep != NULL) 393 *memsizep = memsize; 394 if (flagp != NULL && is16bit) 395 *flagp |= WE_16BIT_ENABLE; 396 if (is790p != NULL) 397 *is790p = is790; 398 return (typestr); 399 } 400