ncr53c500_pccard.c revision 67468
1/* $FreeBSD: head/sys/dev/ncv/ncr53c500_pccard.c 67468 2000-10-23 12:55:51Z non $ */ 2/* $NecBSD: ncr53c500_pisa.c,v 1.28 1998/11/26 01:59:11 honda Exp $ */ 3/* $NetBSD$ */ 4 5/* 6 * [Ported for FreeBSD] 7 * Copyright (c) 2000 8 * Noriaki Mitsunaga, Mitsuru Iwasaki and Takanori Watanabe. 9 * All rights reserved. 10 * [NetBSD for NEC PC-98 series] 11 * Copyright (c) 1995, 1996, 1997, 1998 12 * NetBSD/pc98 porting staff. All rights reserved. 13 * Copyright (c) 1995, 1996, 1997, 1998 14 * Naofumi HONDA. All rights reserved. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. The name of the author may not be used to endorse or promote products 25 * derived from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 28 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 29 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 31 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 32 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 36 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/disklabel.h> 43#if defined(__FreeBSD__) && __FreeBSD_version >= 500001 44#include <sys/bio.h> 45#endif 46#include <sys/buf.h> 47#include <sys/queue.h> 48#include <sys/malloc.h> 49#include <sys/errno.h> 50 51#include <vm/vm.h> 52 53#include <machine/bus.h> 54#include <machine/bus_pio.h> 55#include <i386/isa/isa_device.h> 56 57#include <machine/dvcfg.h> 58 59#if defined(__FreeBSD__) && __FreeBSD_version < 400001 60static struct ncv_softc *ncv_get_softc(int); 61extern struct ncv_softc *ncvdata[]; 62#define DEVPORT_ALLOCSOFTCFUNC ncv_get_softc 63#define DEVPORT_SOFTCARRAY ncvdata 64#endif 65#include <sys/device_port.h> 66 67#include <cam/scsi/scsi_low.h> 68#include <cam/scsi/scsi_low_pisa.h> 69 70#include <dev/ncv/ncr53c500reg.h> 71#include <dev/ncv/ncr53c500hw.h> 72#include <dev/ncv/ncr53c500var.h> 73#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD_version < 400001) 74#include "ncv.h" 75#endif 76 77#define KME_KXLC004_01 0x1 78#define OFFSET_KME_KXLC004_01 0x10 79 80/* pccard support */ 81#include "apm.h" 82#if NAPM > 0 83#include <machine/apm_bios.h> 84#endif /* NAPM > 0 */ 85 86#include "card.h" 87#if NCARD > 0 88#include <sys/kernel.h> 89#include <sys/module.h> 90#include <sys/select.h> 91#include <pccard/cardinfo.h> 92#include <pccard/slot.h> 93 94static int ncvprobe(DEVPORT_PDEVICE devi); 95static int ncvattach(DEVPORT_PDEVICE devi); 96 97static int ncv_card_intr __P((DEVPORT_PDEVICE)); 98static void ncv_card_unload __P((DEVPORT_PDEVICE)); 99#if defined(__FreeBSD__) && __FreeBSD_version < 400001 100static int ncv_card_init __P((DEVPORT_PDEVICE)); 101#endif 102 103#if defined(__FreeBSD__) && __FreeBSD_version >= 400001 104/* 105 * Additional code for FreeBSD new-bus PCCard frontend 106 */ 107 108static void 109ncv_pccard_intr(void * arg) 110{ 111 ncvintr(arg); 112} 113 114static void 115ncv_release_resource(DEVPORT_PDEVICE dev) 116{ 117 struct ncv_softc *sc = device_get_softc(dev); 118 119 if (sc->ncv_intrhand) { 120 bus_teardown_intr(dev, sc->irq_res, sc->ncv_intrhand); 121 } 122 123 if (sc->port_res) { 124 bus_release_resource(dev, SYS_RES_IOPORT, 125 sc->port_rid, sc->port_res); 126 } 127 128 if (sc->irq_res) { 129 bus_release_resource(dev, SYS_RES_IRQ, 130 sc->irq_rid, sc->irq_res); 131 } 132 133 if (sc->mem_res) { 134 bus_release_resource(dev, SYS_RES_MEMORY, 135 sc->mem_rid, sc->mem_res); 136 } 137} 138 139static int 140ncv_alloc_resource(DEVPORT_PDEVICE dev) 141{ 142 struct ncv_softc *sc = device_get_softc(dev); 143 u_int32_t flags = DEVPORT_PDEVFLAGS(dev); 144 u_int iobase = DEVPORT_PDEVIOBASE(dev); 145 u_long maddr, msize; 146 int error; 147 bus_addr_t offset = 0; 148 149 if(flags & KME_KXLC004_01) 150 offset = OFFSET_KME_KXLC004_01; 151 152 sc->port_rid = 0; 153 sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid, 154 iobase+offset, ~0, NCVIOSZ, RF_ACTIVE); 155 if (sc->port_res == NULL) { 156 ncv_release_resource(dev); 157 return(ENOMEM); 158 } 159 160 sc->irq_rid = 0; 161 sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid, 162 0, ~0, 1, RF_ACTIVE); 163 if (sc->irq_res == NULL) { 164 ncv_release_resource(dev); 165 return(ENOMEM); 166 } 167 168 error = bus_get_resource(dev, SYS_RES_MEMORY, 0, &maddr, &msize); 169 if (error) { 170 return(0); /* XXX */ 171 } 172 173 /* no need to allocate memory if not configured */ 174 if (maddr == 0 || msize == 0) { 175 return(0); 176 } 177 178 sc->mem_rid = 0; 179 sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem_rid, 180 0, ~0, msize, RF_ACTIVE); 181 if (sc->mem_res == NULL) { 182 ncv_release_resource(dev); 183 return(ENOMEM); 184 } 185 186 return(0); 187} 188 189static int 190ncv_pccard_probe(DEVPORT_PDEVICE dev) 191{ 192 struct ncv_softc *sc = device_get_softc(dev); 193 int error; 194 195 bzero(sc, sizeof(struct ncv_softc)); 196 197 error = ncv_alloc_resource(dev); 198 if (error) { 199 return(error); 200 } 201 202 if (ncvprobe(dev) == 0) { 203 ncv_release_resource(dev); 204 return(ENXIO); 205 } 206 207 ncv_release_resource(dev); 208 209 return(0); 210} 211 212static int 213ncv_pccard_attach(DEVPORT_PDEVICE dev) 214{ 215 struct ncv_softc *sc = device_get_softc(dev); 216 int error; 217 218 error = ncv_alloc_resource(dev); 219 if (error) { 220 return(error); 221 } 222 223 error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_CAM, 224 ncv_pccard_intr, (void *)sc, &sc->ncv_intrhand); 225 if (error) { 226 ncv_release_resource(dev); 227 return(error); 228 } 229 230 if (ncvattach(dev) == 0) { 231 ncv_release_resource(dev); 232 return(ENXIO); 233 } 234 235 return(0); 236} 237 238static void 239ncv_pccard_detach(DEVPORT_PDEVICE dev) 240{ 241 ncv_card_unload(dev); 242 ncv_release_resource(dev); 243} 244 245static device_method_t ncv_pccard_methods[] = { 246 /* Device interface */ 247 DEVMETHOD(device_probe, ncv_pccard_probe), 248 DEVMETHOD(device_attach, ncv_pccard_attach), 249 DEVMETHOD(device_detach, ncv_pccard_detach), 250 251 { 0, 0 } 252}; 253 254static driver_t ncv_pccard_driver = { 255 "ncv", 256 ncv_pccard_methods, 257 sizeof(struct ncv_softc), 258}; 259 260static devclass_t ncv_devclass; 261 262DRIVER_MODULE(ncv, pccard, ncv_pccard_driver, ncv_devclass, 0, 0); 263 264#else 265 266PCCARD_MODULE(ncv, ncv_card_init, ncv_card_unload, ncv_card_intr, 0, cam_imask); 267 268#endif 269 270#if defined(__FreeBSD__) && __FreeBSD_version < 400001 271static struct ncv_softc * 272ncv_get_softc(int unit) 273{ 274 struct ncv_softc *sc; 275 276 if (unit >= NNCV) { 277 return(NULL); 278 } 279 280 if (ncvdata[unit] == NULL) { 281 sc = malloc(sizeof(struct ncv_softc), M_TEMP,M_NOWAIT); 282 if (sc == NULL) { 283 printf("ncv_get_softc: cannot malloc!\n"); 284 return(NULL); 285 } 286 ncvdata[unit] = sc; 287 } else { 288 sc = ncvdata[unit]; 289 } 290 291 return(sc); 292} 293 294static int 295ncv_card_init(DEVPORT_PDEVICE devi) 296{ 297 int unit = DEVPORT_PDEVUNIT(devi); 298 299 if (NNCV <= unit) 300 return (ENODEV); 301 302 if (ncvprobe(devi) == 0) 303 return (ENXIO); 304 305 if (ncvattach(devi) == 0) 306 return (ENXIO); 307 return (0); 308} 309#endif 310 311static void 312ncv_card_unload(DEVPORT_PDEVICE devi) 313{ 314 struct ncv_softc *sc = DEVPORT_PDEVGET_SOFTC(devi); 315 316 printf("%s: unload\n", sc->sc_sclow.sl_xname); 317 scsi_low_deactivate((struct scsi_low_softc *)sc); 318 scsi_low_dettach(&sc->sc_sclow); 319} 320 321static int 322ncv_card_intr(DEVPORT_PDEVICE devi) 323{ 324 325 ncvintr(DEVPORT_PDEVGET_SOFTC(devi)); 326 return 1; 327} 328 329static int 330ncvprobe(DEVPORT_PDEVICE devi) 331{ 332 int rv; 333 struct ncv_softc *sc = device_get_softc(devi); 334 u_int32_t flags = DEVPORT_PDEVFLAGS(devi); 335 336#if defined(__FreeBSD__) && __FreeBSD_version >= 400001 337 rv = ncvprobesubr(rman_get_bustag(sc->port_res), 338 rman_get_bushandle(sc->port_res), 339 flags, NCV_HOSTID); 340#else 341 bus_addr_t offset = 0; 342 u_int iobase = DEVPORT_PDEVIOBASE(devi); 343 344 if(flags & KME_KXLC004_01) 345 offset = OFFSET_KME_KXLC004_01; 346 347 rv = ncvprobesubr(I386_BUS_SPACE_IO, 348 iobase + offset, 349 flags, NCV_HOSTID); 350#endif 351 352 return rv; 353} 354 355static int 356ncvattach(DEVPORT_PDEVICE devi) 357{ 358 struct ncv_softc *sc; 359 struct scsi_low_softc *slp; 360 u_int32_t flags = DEVPORT_PDEVFLAGS(devi); 361#if defined(__FreeBSD__) && __FreeBSD_version < 400001 362 int unit = DEVPORT_PDEVUNIT(devi); 363 bus_addr_t offset = 0; 364 u_int iobase = DEVPORT_PDEVIOBASE(devi); 365#endif 366 char dvname[16]; /* SCSI_LOW_DVNAME_LEN */ 367 368 strcpy(dvname, "ncv"); 369 370#if defined(__FreeBSD__) && __FreeBSD_version < 400001 371 if (unit >= NNCV) 372 { 373 printf("%s: unit number too high\n", dvname); 374 return (0); 375 } 376 377 if (iobase == 0) 378 { 379 printf("%s: no ioaddr is given\n", dvname); 380 return (0); 381 } 382 383 if(flags & KME_KXLC004_01) 384 offset = OFFSET_KME_KXLC004_01; 385#endif 386 387 sc = DEVPORT_PDEVALLOC_SOFTC(devi); 388 if (sc == NULL) { 389 return(0); 390 } 391 392 slp = &sc->sc_sclow; 393#if defined(__FreeBSD__) && __FreeBSD_version >= 400001 394 slp->sl_dev = devi; 395 sc->sc_iot = rman_get_bustag(sc->port_res); 396 sc->sc_ioh = rman_get_bushandle(sc->port_res); 397#else 398 bzero(sc, sizeof(struct ncv_softc)); 399 strcpy(slp->sl_dev.dv_xname, dvname); 400 slp->sl_dev.dv_unit = unit; 401 sc->sc_iot = I386_BUS_SPACE_IO; 402 sc->sc_ioh = iobase + offset; 403#endif 404 405 slp->sl_hostid = NCV_HOSTID; 406 slp->sl_cfgflags = flags; 407 408 ncvattachsubr(sc); 409 410 sc->sc_ih = ncvintr; 411 412 return(NCVIOSZ); 413} 414#endif /* NCARD */ 415