ncr53c500_pccard.c revision 127135
112657Skvn/* $NecBSD: ncr53c500_pisa.c,v 1.28 1998/11/26 01:59:11 honda Exp $ */ 212657Skvn/* $NetBSD$ */ 312657Skvn 412657Skvn/* 512657Skvn * [Ported for FreeBSD] 612657Skvn * Copyright (c) 2000 712657Skvn * Noriaki Mitsunaga, Mitsuru Iwasaki and Takanori Watanabe. 812657Skvn * All rights reserved. 912657Skvn * [NetBSD for NEC PC-98 series] 1012657Skvn * Copyright (c) 1995, 1996, 1997, 1998 1112657Skvn * NetBSD/pc98 porting staff. All rights reserved. 1212657Skvn * Copyright (c) 1995, 1996, 1997, 1998 1312657Skvn * Naofumi HONDA. All rights reserved. 1412657Skvn * 1512657Skvn * Redistribution and use in source and binary forms, with or without 1612657Skvn * modification, are permitted provided that the following conditions 1712657Skvn * are met: 1812657Skvn * 1. Redistributions of source code must retain the above copyright 1912657Skvn * notice, this list of conditions and the following disclaimer. 2012657Skvn * 2. Redistributions in binary form must reproduce the above copyright 2112657Skvn * notice, this list of conditions and the following disclaimer in the 2212657Skvn * documentation and/or other materials provided with the distribution. 2312657Skvn * 3. The name of the author may not be used to endorse or promote products 2412657Skvn * derived from this software without specific prior written permission. 2512657Skvn * 2612657Skvn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2712657Skvn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2812657Skvn * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2912657Skvn * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 3012657Skvn * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 3112657Skvn * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 3212657Skvn * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3312657Skvn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3412657Skvn * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3512657Skvn * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3612657Skvn * POSSIBILITY OF SUCH DAMAGE. 3712657Skvn */ 3812657Skvn 3912657Skvn#include <sys/cdefs.h> 4012657Skvn__FBSDID("$FreeBSD: head/sys/dev/ncv/ncr53c500_pccard.c 127135 2004-03-17 17:50:55Z njl $"); 4112657Skvn 4212657Skvn#include <sys/param.h> 4312657Skvn#include <sys/systm.h> 4412657Skvn#include <sys/malloc.h> 4512657Skvn#include <sys/errno.h> 4612657Skvn 4712657Skvn#include <machine/bus.h> 4812657Skvn#include <machine/bus_pio.h> 4912657Skvn#include <compat/netbsd/dvcfg.h> 5012657Skvn 5112657Skvn#include <sys/device_port.h> 5212657Skvn 5312657Skvn#include <dev/pccard/pccarddevs.h> 5412657Skvn#include <dev/pccard/pccardvar.h> 5512657Skvn 5612657Skvn#include <cam/scsi/scsi_low.h> 5712657Skvn#include <cam/scsi/scsi_low_pisa.h> 5812657Skvn 5912657Skvn#include <dev/ncv/ncr53c500reg.h> 6012657Skvn#include <dev/ncv/ncr53c500hw.h> 6112657Skvn#include <dev/ncv/ncr53c500var.h> 6212657Skvn 6312657Skvn#define KME_KXLC004_01 0x100 6412657Skvn#define OFFSET_KME_KXLC004_01 0x10 6512657Skvn 6612657Skvn#include <sys/kernel.h> 6712657Skvn#include <sys/module.h> 6812657Skvn#if !defined(__FreeBSD__) || __FreeBSD_version < 500014 6912657Skvn#include <sys/select.h> 7012657Skvn#endif 7112657Skvn#include <pccard/cardinfo.h> 7212657Skvn#include <pccard/slot.h> 7312657Skvn 7412657Skvnstatic int ncvprobe(DEVPORT_PDEVICE devi); 7512657Skvnstatic int ncvattach(DEVPORT_PDEVICE devi); 7612657Skvn 7712657Skvnstatic void ncv_card_unload(DEVPORT_PDEVICE); 7812657Skvn 7912657Skvnstatic const struct ncv_product { 8012657Skvn struct pccard_product prod; 8112657Skvn int flags; 8212657Skvn} ncv_products[] = { 8312657Skvn { PCMCIA_CARD(EPSON, SC200, 0), 0}, 8412657Skvn { PCMCIA_CARD(PANASONIC, KXLC002, 0), 0xb4d00000 }, 8512657Skvn { PCMCIA_CARD(PANASONIC, KXLC004, 0), 0xb4d00100 }, 8612657Skvn { PCMCIA_CARD(MACNICA, MPS100, 0), 0xb6250000 }, 8712657Skvn { PCMCIA_CARD(MACNICA, MPS110, 0), 0 }, 8812657Skvn { PCMCIA_CARD(NEC, PC9801N_J03R, 0), 0 }, 8912657Skvn { PCMCIA_CARD(NEWMEDIA, BASICS_SCSI, 0), 0 }, 9012657Skvn { PCMCIA_CARD(QLOGIC, PC05, 0), 0x84d00000 }, 9112657Skvn#define FLAGS_REX5572 0x84d00000 9212657Skvn { PCMCIA_CARD(RATOC, REX5572, 0), FLAGS_REX5572 }, 9312657Skvn { PCMCIA_CARD(RATOC, REX9530, 0), 0x84d00000 }, 9412657Skvn { { NULL }, 0 } 9512657Skvn}; 9612657Skvn 9712657Skvn/* 9812657Skvn * Additional code for FreeBSD new-bus PCCard frontend 9912657Skvn */ 10012657Skvn 10112657Skvnstatic void 10212657Skvnncv_pccard_intr(void * arg) 10312657Skvn{ 10412657Skvn ncvintr(arg); 10512657Skvn} 10612657Skvn 10712657Skvnstatic void 10812657Skvnncv_release_resource(DEVPORT_PDEVICE dev) 10912657Skvn{ 11012657Skvn struct ncv_softc *sc = device_get_softc(dev); 11112657Skvn 11212657Skvn if (sc->ncv_intrhand) { 11312657Skvn bus_teardown_intr(dev, sc->irq_res, sc->ncv_intrhand); 11412657Skvn } 11512657Skvn 11612657Skvn if (sc->port_res) { 11712657Skvn bus_release_resource(dev, SYS_RES_IOPORT, 11812657Skvn sc->port_rid, sc->port_res); 11912657Skvn } 12012657Skvn 12112657Skvn if (sc->port_res_dmy) { 12212657Skvn bus_release_resource(dev, SYS_RES_IOPORT, 12312657Skvn sc->port_rid_dmy, sc->port_res_dmy); 12412657Skvn } 12512657Skvn 12612657Skvn if (sc->irq_res) { 12712657Skvn bus_release_resource(dev, SYS_RES_IRQ, 12812657Skvn sc->irq_rid, sc->irq_res); 12912657Skvn } 13012657Skvn 13112657Skvn if (sc->mem_res) { 13212657Skvn bus_release_resource(dev, SYS_RES_MEMORY, 13312657Skvn sc->mem_rid, sc->mem_res); 13412657Skvn } 13512657Skvn} 13612657Skvn 13712657Skvnstatic int 13812657Skvnncv_alloc_resource(DEVPORT_PDEVICE dev) 13912657Skvn{ 14012657Skvn struct ncv_softc *sc = device_get_softc(dev); 14112657Skvn u_int32_t flags = DEVPORT_PDEVFLAGS(dev); 14212657Skvn u_long ioaddr, iosize, maddr, msize; 14312657Skvn int error; 14412657Skvn bus_addr_t offset = 0; 14512657Skvn 14612657Skvn if(flags & KME_KXLC004_01) 14712657Skvn offset = OFFSET_KME_KXLC004_01; 14812657Skvn 14912657Skvn error = bus_get_resource(dev, SYS_RES_IOPORT, 0, &ioaddr, &iosize); 15012657Skvn if (error || (iosize < (offset + NCVIOSZ))) { 15112657Skvn return(ENOMEM); 15212657Skvn } 15312657Skvn 15412657Skvn sc->port_rid = 0; 15512657Skvn sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid, 15612657Skvn ioaddr+offset, ioaddr+iosize-offset, 15712657Skvn iosize-offset, RF_ACTIVE); 15812657Skvn if (sc->port_res == NULL) { 15912657Skvn ncv_release_resource(dev); 16012657Skvn return(ENOMEM); 16112657Skvn } 16212657Skvn 16312657Skvn if (offset != 0) { 16412657Skvn sc->port_rid_dmy = 0; 16512657Skvn sc->port_res_dmy = bus_alloc_resource(dev, SYS_RES_IOPORT, 16612657Skvn &sc->port_rid_dmy, 16712657Skvn ioaddr, ioaddr+offset, offset, 16812657Skvn RF_ACTIVE); 16912657Skvn if (sc->port_res_dmy == NULL) { 17012657Skvn printf("Warning: cannot allocate IOPORT partially.\n"); 17112657Skvn } 17212657Skvn } else { 17312657Skvn sc->port_rid_dmy = 0; 17412657Skvn sc->port_res_dmy = NULL; 17512657Skvn } 17612657Skvn 17712657Skvn sc->irq_rid = 0; 17812657Skvn sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid, 17912657Skvn RF_ACTIVE); 18012657Skvn if (sc->irq_res == NULL) { 18112657Skvn ncv_release_resource(dev); 18212657Skvn return(ENOMEM); 18312657Skvn } 18412657Skvn 18512657Skvn error = bus_get_resource(dev, SYS_RES_MEMORY, 0, &maddr, &msize); 18612657Skvn if (error) { 18712657Skvn return(0); /* XXX */ 18812657Skvn } 18912657Skvn 19012657Skvn /* no need to allocate memory if not configured */ 19112657Skvn if (maddr == 0 || msize == 0) { 19212657Skvn return(0); 19312657Skvn } 19412657Skvn 19512657Skvn sc->mem_rid = 0; 19612657Skvn sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid, 19712657Skvn RF_ACTIVE); 19812657Skvn if (sc->mem_res == NULL) { 19912657Skvn ncv_release_resource(dev); 20012657Skvn return(ENOMEM); 20112657Skvn } 20212657Skvn 20312657Skvn return(0); 20412657Skvn} 20512657Skvn 20612657Skvnstatic int ncv_pccard_match(device_t dev) 20712657Skvn{ 20812657Skvn const struct ncv_product *pp; 20912657Skvn const char *vendorstr; 21012657Skvn const char *prodstr; 21112657Skvn 21212657Skvn if ((pp = (const struct ncv_product *) pccard_product_lookup(dev, 21312657Skvn (const struct pccard_product *) ncv_products, 21412657Skvn sizeof(ncv_products[0]), NULL)) != NULL) { 21512657Skvn if (pp->prod.pp_name != NULL) 21612657Skvn device_set_desc(dev, pp->prod.pp_name); 21712657Skvn device_set_flags(dev, pp->flags); 21812657Skvn return(0); 21912657Skvn } 22012657Skvn if (pccard_get_vendor_str(dev, &vendorstr)) 22112657Skvn return(EIO); 22212657Skvn if (pccard_get_product_str(dev, &prodstr)) 22312657Skvn return(EIO); 22412657Skvn if (strcmp(vendorstr, "RATOC System Inc.") == 0 && 22512657Skvn strncmp(prodstr, "SOUND/SCSI2 CARD", 16) == 0) { 22612657Skvn device_set_desc(dev, "RATOC REX-5572"); 22712657Skvn device_set_flags(dev, FLAGS_REX5572); 22812657Skvn return (0); 22912657Skvn } 23012657Skvn return(EIO); 23112657Skvn} 23212657Skvn 23312657Skvnstatic int 23412657Skvnncv_pccard_probe(DEVPORT_PDEVICE dev) 23512657Skvn{ 23612657Skvn struct ncv_softc *sc = device_get_softc(dev); 23712657Skvn int error; 23812657Skvn 23912657Skvn bzero(sc, sizeof(struct ncv_softc)); 24012657Skvn 24112657Skvn error = ncv_alloc_resource(dev); 24212657Skvn if (error) { 24312657Skvn return(error); 24412657Skvn } 24512657Skvn 24612657Skvn if (ncvprobe(dev) == 0) { 24712657Skvn ncv_release_resource(dev); 24812657Skvn return(ENXIO); 24912657Skvn } 25012657Skvn 25112657Skvn ncv_release_resource(dev); 25212657Skvn 25312657Skvn return(0); 25412657Skvn} 25512657Skvn 25612657Skvnstatic int 25712657Skvnncv_pccard_attach(DEVPORT_PDEVICE dev) 25812657Skvn{ 25912657Skvn struct ncv_softc *sc = device_get_softc(dev); 26012657Skvn int error; 26112657Skvn 26212657Skvn error = ncv_alloc_resource(dev); 26312657Skvn if (error) { 26412657Skvn return(error); 26512657Skvn } 26612657Skvn 26712657Skvn error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_CAM | INTR_ENTROPY, 26812657Skvn ncv_pccard_intr, (void *)sc, &sc->ncv_intrhand); 26912657Skvn if (error) { 27012657Skvn ncv_release_resource(dev); 27112657Skvn return(error); 27212657Skvn } 27312657Skvn 27412657Skvn if (ncvattach(dev) == 0) { 27512657Skvn ncv_release_resource(dev); 27612657Skvn return(ENXIO); 27712657Skvn } 27812657Skvn 27912657Skvn return(0); 28012657Skvn} 28112657Skvn 28212657Skvnstatic void 28312657Skvnncv_pccard_detach(DEVPORT_PDEVICE dev) 28412657Skvn{ 28512657Skvn ncv_card_unload(dev); 28612657Skvn ncv_release_resource(dev); 28712657Skvn} 28812657Skvn 28912657Skvnstatic device_method_t ncv_pccard_methods[] = { 29012657Skvn /* Device interface */ 29112657Skvn DEVMETHOD(device_probe, pccard_compat_probe), 29212657Skvn DEVMETHOD(device_attach, pccard_compat_attach), 29312657Skvn DEVMETHOD(device_detach, ncv_pccard_detach), 29412657Skvn 29512657Skvn /* Card interface */ 29612657Skvn DEVMETHOD(card_compat_match, ncv_pccard_match), 29712657Skvn DEVMETHOD(card_compat_probe, ncv_pccard_probe), 29812657Skvn DEVMETHOD(card_compat_attach, ncv_pccard_attach), 29912657Skvn 30012657Skvn { 0, 0 } 30112657Skvn}; 30212657Skvn 30312657Skvnstatic driver_t ncv_pccard_driver = { 30412657Skvn "ncv", 30512657Skvn ncv_pccard_methods, 30612657Skvn sizeof(struct ncv_softc), 30712657Skvn}; 30812657Skvn 30912657Skvnstatic devclass_t ncv_devclass; 31012657Skvn 31112657SkvnMODULE_DEPEND(ncv, scsi_low, 1, 1, 1); 31212657SkvnDRIVER_MODULE(ncv, pccard, ncv_pccard_driver, ncv_devclass, 0, 0); 31312657Skvn 31412657Skvnstatic void 31512657Skvnncv_card_unload(DEVPORT_PDEVICE devi) 31612657Skvn{ 31712657Skvn struct ncv_softc *sc = DEVPORT_PDEVGET_SOFTC(devi); 31812657Skvn intrmask_t s; 31912657Skvn 32012657Skvn printf("%s: unload\n", sc->sc_sclow.sl_xname); 32112657Skvn s = splcam(); 32212657Skvn scsi_low_deactivate((struct scsi_low_softc *)sc); 32312657Skvn scsi_low_dettach(&sc->sc_sclow); 32412657Skvn splx(s); 32512657Skvn} 32612657Skvn 32712657Skvnstatic int 32812657Skvnncvprobe(DEVPORT_PDEVICE devi) 32912657Skvn{ 33012657Skvn int rv; 33112657Skvn struct ncv_softc *sc = device_get_softc(devi); 33212657Skvn u_int32_t flags = DEVPORT_PDEVFLAGS(devi); 33312657Skvn 33412657Skvn rv = ncvprobesubr(rman_get_bustag(sc->port_res), 33512657Skvn rman_get_bushandle(sc->port_res), 33612657Skvn flags, NCV_HOSTID); 33712657Skvn 33812657Skvn return rv; 33912657Skvn} 34012657Skvn 34112657Skvnstatic int 34212657Skvnncvattach(DEVPORT_PDEVICE devi) 34312657Skvn{ 34412657Skvn struct ncv_softc *sc; 34512657Skvn struct scsi_low_softc *slp; 34612657Skvn u_int32_t flags = DEVPORT_PDEVFLAGS(devi); 34712657Skvn intrmask_t s; 34812657Skvn char dvname[16]; /* SCSI_LOW_DVNAME_LEN */ 34912657Skvn 35012657Skvn strcpy(dvname, "ncv"); 35112657Skvn 35212657Skvn sc = DEVPORT_PDEVALLOC_SOFTC(devi); 35312657Skvn if (sc == NULL) { 35412657Skvn return(0); 35512657Skvn } 35612657Skvn 35712657Skvn slp = &sc->sc_sclow; 35812657Skvn slp->sl_dev = devi; 35912657Skvn sc->sc_iot = rman_get_bustag(sc->port_res); 36012657Skvn sc->sc_ioh = rman_get_bushandle(sc->port_res); 36112657Skvn 36212657Skvn slp->sl_hostid = NCV_HOSTID; 36312657Skvn slp->sl_cfgflags = flags; 36412657Skvn 36512657Skvn s = splcam(); 36612657Skvn ncvattachsubr(sc); 36712657Skvn splx(s); 36812657Skvn 36912657Skvn return(NCVIOSZ); 37012657Skvn} 37112657Skvn