ncr53c500_pccard.c revision 70834
1/* $FreeBSD: head/sys/dev/ncv/ncr53c500_pccard.c 70834 2001-01-09 04:33:49Z wollman $ */ 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 0x100 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#if !defined(__FreeBSD__) || __FreeBSD_version < 500014 91#include <sys/select.h> 92#endif 93#include <pccard/cardinfo.h> 94#include <pccard/slot.h> 95 96static int ncvprobe(DEVPORT_PDEVICE devi); 97static int ncvattach(DEVPORT_PDEVICE devi); 98 99static int ncv_card_intr __P((DEVPORT_PDEVICE)); 100static void ncv_card_unload __P((DEVPORT_PDEVICE)); 101#if defined(__FreeBSD__) && __FreeBSD_version < 400001 102static int ncv_card_init __P((DEVPORT_PDEVICE)); 103#endif 104 105#if defined(__FreeBSD__) && __FreeBSD_version >= 400001 106/* 107 * Additional code for FreeBSD new-bus PCCard frontend 108 */ 109 110static void 111ncv_pccard_intr(void * arg) 112{ 113 ncvintr(arg); 114} 115 116static void 117ncv_release_resource(DEVPORT_PDEVICE dev) 118{ 119 struct ncv_softc *sc = device_get_softc(dev); 120 121 if (sc->ncv_intrhand) { 122 bus_teardown_intr(dev, sc->irq_res, sc->ncv_intrhand); 123 } 124 125 if (sc->port_res) { 126 bus_release_resource(dev, SYS_RES_IOPORT, 127 sc->port_rid, sc->port_res); 128 } 129 130 if (sc->irq_res) { 131 bus_release_resource(dev, SYS_RES_IRQ, 132 sc->irq_rid, sc->irq_res); 133 } 134 135 if (sc->mem_res) { 136 bus_release_resource(dev, SYS_RES_MEMORY, 137 sc->mem_rid, sc->mem_res); 138 } 139} 140 141static int 142ncv_alloc_resource(DEVPORT_PDEVICE dev) 143{ 144 struct ncv_softc *sc = device_get_softc(dev); 145 u_int32_t flags = DEVPORT_PDEVFLAGS(dev); 146 u_int iobase = DEVPORT_PDEVIOBASE(dev); 147 u_long maddr, msize; 148 int error; 149 bus_addr_t offset = 0; 150 151 if(flags & KME_KXLC004_01) 152 offset = OFFSET_KME_KXLC004_01; 153 154 sc->port_rid = 0; 155 sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid, 156 iobase+offset, ~0, NCVIOSZ, RF_ACTIVE); 157 if (sc->port_res == NULL) { 158 ncv_release_resource(dev); 159 return(ENOMEM); 160 } 161 162 sc->irq_rid = 0; 163 sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid, 164 0, ~0, 1, RF_ACTIVE); 165 if (sc->irq_res == NULL) { 166 ncv_release_resource(dev); 167 return(ENOMEM); 168 } 169 170 error = bus_get_resource(dev, SYS_RES_MEMORY, 0, &maddr, &msize); 171 if (error) { 172 return(0); /* XXX */ 173 } 174 175 /* no need to allocate memory if not configured */ 176 if (maddr == 0 || msize == 0) { 177 return(0); 178 } 179 180 sc->mem_rid = 0; 181 sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem_rid, 182 0, ~0, msize, RF_ACTIVE); 183 if (sc->mem_res == NULL) { 184 ncv_release_resource(dev); 185 return(ENOMEM); 186 } 187 188 return(0); 189} 190 191static int 192ncv_pccard_probe(DEVPORT_PDEVICE dev) 193{ 194 struct ncv_softc *sc = device_get_softc(dev); 195 int error; 196 197 bzero(sc, sizeof(struct ncv_softc)); 198 199 error = ncv_alloc_resource(dev); 200 if (error) { 201 return(error); 202 } 203 204 if (ncvprobe(dev) == 0) { 205 ncv_release_resource(dev); 206 return(ENXIO); 207 } 208 209 ncv_release_resource(dev); 210 211 return(0); 212} 213 214static int 215ncv_pccard_attach(DEVPORT_PDEVICE dev) 216{ 217 struct ncv_softc *sc = device_get_softc(dev); 218 int error; 219 220 error = ncv_alloc_resource(dev); 221 if (error) { 222 return(error); 223 } 224 225 error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_CAM, 226 ncv_pccard_intr, (void *)sc, &sc->ncv_intrhand); 227 if (error) { 228 ncv_release_resource(dev); 229 return(error); 230 } 231 232 if (ncvattach(dev) == 0) { 233 ncv_release_resource(dev); 234 return(ENXIO); 235 } 236 237 return(0); 238} 239 240static void 241ncv_pccard_detach(DEVPORT_PDEVICE dev) 242{ 243 ncv_card_unload(dev); 244 ncv_release_resource(dev); 245} 246 247static device_method_t ncv_pccard_methods[] = { 248 /* Device interface */ 249 DEVMETHOD(device_probe, ncv_pccard_probe), 250 DEVMETHOD(device_attach, ncv_pccard_attach), 251 DEVMETHOD(device_detach, ncv_pccard_detach), 252 253 { 0, 0 } 254}; 255 256static driver_t ncv_pccard_driver = { 257 "ncv", 258 ncv_pccard_methods, 259 sizeof(struct ncv_softc), 260}; 261 262static devclass_t ncv_devclass; 263 264DRIVER_MODULE(ncv, pccard, ncv_pccard_driver, ncv_devclass, 0, 0); 265 266#else 267 268PCCARD_MODULE(ncv, ncv_card_init, ncv_card_unload, ncv_card_intr, 0, cam_imask); 269 270#endif 271 272#if defined(__FreeBSD__) && __FreeBSD_version < 400001 273static struct ncv_softc * 274ncv_get_softc(int unit) 275{ 276 struct ncv_softc *sc; 277 278 if (unit >= NNCV) { 279 return(NULL); 280 } 281 282 if (ncvdata[unit] == NULL) { 283 sc = malloc(sizeof(struct ncv_softc), M_TEMP,M_NOWAIT); 284 if (sc == NULL) { 285 printf("ncv_get_softc: cannot malloc!\n"); 286 return(NULL); 287 } 288 ncvdata[unit] = sc; 289 } else { 290 sc = ncvdata[unit]; 291 } 292 293 return(sc); 294} 295 296static int 297ncv_card_init(DEVPORT_PDEVICE devi) 298{ 299 int unit = DEVPORT_PDEVUNIT(devi); 300 301 if (NNCV <= unit) 302 return (ENODEV); 303 304 if (ncvprobe(devi) == 0) 305 return (ENXIO); 306 307 if (ncvattach(devi) == 0) 308 return (ENXIO); 309 return (0); 310} 311#endif 312 313static void 314ncv_card_unload(DEVPORT_PDEVICE devi) 315{ 316 struct ncv_softc *sc = DEVPORT_PDEVGET_SOFTC(devi); 317 318 printf("%s: unload\n", sc->sc_sclow.sl_xname); 319 scsi_low_deactivate((struct scsi_low_softc *)sc); 320 scsi_low_dettach(&sc->sc_sclow); 321} 322 323static int 324ncv_card_intr(DEVPORT_PDEVICE devi) 325{ 326 327 ncvintr(DEVPORT_PDEVGET_SOFTC(devi)); 328 return 1; 329} 330 331static int 332ncvprobe(DEVPORT_PDEVICE devi) 333{ 334 int rv; 335 struct ncv_softc *sc = device_get_softc(devi); 336 u_int32_t flags = DEVPORT_PDEVFLAGS(devi); 337 338#if defined(__FreeBSD__) && __FreeBSD_version >= 400001 339 rv = ncvprobesubr(rman_get_bustag(sc->port_res), 340 rman_get_bushandle(sc->port_res), 341 flags, NCV_HOSTID); 342#else 343 bus_addr_t offset = 0; 344 u_int iobase = DEVPORT_PDEVIOBASE(devi); 345 346 if(flags & KME_KXLC004_01) 347 offset = OFFSET_KME_KXLC004_01; 348 349 rv = ncvprobesubr(I386_BUS_SPACE_IO, 350 iobase + offset, 351 flags, NCV_HOSTID); 352#endif 353 354 return rv; 355} 356 357static int 358ncvattach(DEVPORT_PDEVICE devi) 359{ 360 struct ncv_softc *sc; 361 struct scsi_low_softc *slp; 362 u_int32_t flags = DEVPORT_PDEVFLAGS(devi); 363#if defined(__FreeBSD__) && __FreeBSD_version < 400001 364 int unit = DEVPORT_PDEVUNIT(devi); 365 bus_addr_t offset = 0; 366 u_int iobase = DEVPORT_PDEVIOBASE(devi); 367#endif 368 char dvname[16]; /* SCSI_LOW_DVNAME_LEN */ 369 370 strcpy(dvname, "ncv"); 371 372#if defined(__FreeBSD__) && __FreeBSD_version < 400001 373 if (unit >= NNCV) 374 { 375 printf("%s: unit number too high\n", dvname); 376 return (0); 377 } 378 379 if (iobase == 0) 380 { 381 printf("%s: no ioaddr is given\n", dvname); 382 return (0); 383 } 384 385 if(flags & KME_KXLC004_01) 386 offset = OFFSET_KME_KXLC004_01; 387#endif 388 389 sc = DEVPORT_PDEVALLOC_SOFTC(devi); 390 if (sc == NULL) { 391 return(0); 392 } 393 394 slp = &sc->sc_sclow; 395#if defined(__FreeBSD__) && __FreeBSD_version >= 400001 396 slp->sl_dev = devi; 397 sc->sc_iot = rman_get_bustag(sc->port_res); 398 sc->sc_ioh = rman_get_bushandle(sc->port_res); 399#else 400 bzero(sc, sizeof(struct ncv_softc)); 401 strcpy(slp->sl_dev.dv_xname, dvname); 402 slp->sl_dev.dv_unit = unit; 403 sc->sc_iot = I386_BUS_SPACE_IO; 404 sc->sc_ioh = iobase + offset; 405#endif 406 407 slp->sl_hostid = NCV_HOSTID; 408 slp->sl_cfgflags = flags; 409 410 ncvattachsubr(sc); 411 412 sc->sc_ih = ncvintr; 413 414 return(NCVIOSZ); 415} 416#endif /* NCARD */ 417