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