diff --git a/sys/dev/advansys/adv_pci.c b/sys/dev/advansys/adv_pci.c index ef938e38efeb..b295853a9537 100644 --- a/sys/dev/advansys/adv_pci.c +++ b/sys/dev/advansys/adv_pci.c @@ -1,336 +1,335 @@ /*- * Device probe and attach routines for the following * Advanced Systems Inc. SCSI controllers: * * Connectivity Products: * ABP902/3902 - Bus-Master PCI (16 CDB) * ABP3905 - Bus-Master PCI (16 CDB) * ABP915 - Bus-Master PCI (16 CDB) * ABP920 - Bus-Master PCI (16 CDB) * ABP3922 - Bus-Master PCI (16 CDB) * ABP3925 - Bus-Master PCI (16 CDB) * ABP930 - Bus-Master PCI (16 CDB) * * ABP930U - Bus-Master PCI Ultra (16 CDB) * ABP930UA - Bus-Master PCI Ultra (16 CDB) * ABP960 - Bus-Master PCI MAC/PC (16 CDB) ** * ABP960U - Bus-Master PCI MAC/PC (16 CDB) ** * * Single Channel Products: * ABP940 - Bus-Master PCI (240 CDB) * ABP940U - Bus-Master PCI Ultra (240 CDB) * ABP940UA/3940UA - Bus-Master PCI Ultra (240 CDB) * ABP3960UA - Bus-Master PCI MAC/PC (240 CDB) * ABP970 - Bus-Master PCI MAC/PC (240 CDB) * ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB) * * Dual Channel Products: * ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel) * ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel) * ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel) * ABP980UA/3980UA - Four Channel Bus-Master PCI Ultra (16 CDB Per Chan.) * * Footnotes: * * This board has been sold by SIIG as the Fast SCSI Pro PCI. * ** This board has been sold by Iomega as a Jaz Jet PCI adapter. * * Copyright (c) 1997 Justin Gibbs. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #define PCI_BASEADR0 PCIR_BAR(0) /* I/O Address */ #define PCI_BASEADR1 PCIR_BAR(1) /* Mem I/O Address */ #define PCI_DEVICE_ID_ADVANSYS_1200A 0x110010CD #define PCI_DEVICE_ID_ADVANSYS_1200B 0x120010CD #define PCI_DEVICE_ID_ADVANSYS_3000 0x130010CD #define PCI_DEVICE_REV_ADVANSYS_3150 0x02 #define PCI_DEVICE_REV_ADVANSYS_3050 0x03 #define ADV_PCI_MAX_DMA_ADDR (0xFFFFFFFFL) #define ADV_PCI_MAX_DMA_COUNT (0xFFFFFFFFL) static int adv_pci_probe(device_t); static int adv_pci_attach(device_t); /* * The overrun buffer shared amongst all PCI adapters. */ static void* overrun_buf; static bus_dma_tag_t overrun_dmat; static bus_dmamap_t overrun_dmamap; static bus_addr_t overrun_physbase; static int adv_pci_probe(device_t dev) { int rev = pci_get_revid(dev); switch (pci_get_devid(dev)) { case PCI_DEVICE_ID_ADVANSYS_1200A: device_set_desc(dev, "AdvanSys ASC1200A SCSI controller"); return BUS_PROBE_DEFAULT; case PCI_DEVICE_ID_ADVANSYS_1200B: device_set_desc(dev, "AdvanSys ASC1200B SCSI controller"); return BUS_PROBE_DEFAULT; case PCI_DEVICE_ID_ADVANSYS_3000: if (rev == PCI_DEVICE_REV_ADVANSYS_3150) { device_set_desc(dev, "AdvanSys ASC3150 SCSI controller"); return BUS_PROBE_DEFAULT; } else if (rev == PCI_DEVICE_REV_ADVANSYS_3050) { device_set_desc(dev, "AdvanSys ASC3030/50 SCSI controller"); return BUS_PROBE_DEFAULT; } else if (rev >= PCI_DEVICE_REV_ADVANSYS_3150) { device_set_desc(dev, "Unknown AdvanSys controller"); return BUS_PROBE_DEFAULT; } break; default: break; } return ENXIO; } static int adv_pci_attach(device_t dev) { struct adv_softc *adv; u_int32_t id; u_int32_t command; int error, rid, irqrid; void *ih; struct resource *iores, *irqres; /* * Determine the chip version. */ id = pci_read_config(dev, PCIR_DEVVENDOR, /*bytes*/4); command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); /* * These cards do not allow memory mapped accesses, so we must * ensure that I/O accesses are available or we won't be able * to talk to them. */ if ((command & (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) != (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) { command |= PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN; pci_write_config(dev, PCIR_COMMAND, command, /*bytes*/1); } /* * Early chips can't handle non-zero latency timer settings. */ if (id == PCI_DEVICE_ID_ADVANSYS_1200A || id == PCI_DEVICE_ID_ADVANSYS_1200B) { pci_write_config(dev, PCIR_LATTIMER, /*value*/0, /*bytes*/1); } rid = PCI_BASEADR0; iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); if (iores == NULL) return ENXIO; if (adv_find_signature(rman_get_bustag(iores), rman_get_bushandle(iores)) == 0) { bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); return ENXIO; } adv = adv_alloc(dev, rman_get_bustag(iores), rman_get_bushandle(iores)); if (adv == NULL) { bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); return ENXIO; } /* Allocate a dmatag for our transfer DMA maps */ - /* XXX Should be a child of the PCI bus dma tag */ error = bus_dma_tag_create( /* parent */ bus_get_dma_tag(dev), /* alignment */ 1, /* boundary */ 0, /* lowaddr */ ADV_PCI_MAX_DMA_ADDR, /* highaddr */ BUS_SPACE_MAXADDR, /* filter */ NULL, /* filterarg */ NULL, /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, /* nsegments */ ~0, /* maxsegsz */ ADV_PCI_MAX_DMA_COUNT, /* flags */ 0, /* lockfunc */ busdma_lock_mutex, /* lockarg */ &Giant, &adv->parent_dmat); if (error != 0) { printf("%s: Could not allocate DMA tag - error %d\n", adv_name(adv), error); adv_free(adv); bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); return ENXIO; } adv->init_level++; if (overrun_buf == NULL) { /* Need to allocate our overrun buffer */ if (bus_dma_tag_create( /* parent */ adv->parent_dmat, /* alignment */ 8, /* boundary */ 0, /* lowaddr */ ADV_PCI_MAX_DMA_ADDR, /* highaddr */ BUS_SPACE_MAXADDR, /* filter */ NULL, /* filterarg */ NULL, /* maxsize */ ADV_OVERRUN_BSIZE, /* nsegments */ 1, /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, /* flags */ 0, /* lockfunc */ busdma_lock_mutex, /* lockarg */ &Giant, &overrun_dmat) != 0) { bus_dma_tag_destroy(adv->parent_dmat); adv_free(adv); bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); return ENXIO; } if (bus_dmamem_alloc(overrun_dmat, &overrun_buf, BUS_DMA_NOWAIT, &overrun_dmamap) != 0) { bus_dma_tag_destroy(overrun_dmat); bus_dma_tag_destroy(adv->parent_dmat); adv_free(adv); bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); return ENXIO; } /* And permanently map it in */ bus_dmamap_load(overrun_dmat, overrun_dmamap, overrun_buf, ADV_OVERRUN_BSIZE, adv_map, &overrun_physbase, /*flags*/0); } adv->overrun_physbase = overrun_physbase; /* * Stop the chip. */ ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT); ADV_OUTW(adv, ADV_CHIP_STATUS, 0); adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION); adv->type = ADV_PCI; /* * Setup active negation and signal filtering. */ { u_int8_t extra_cfg; if (adv->chip_version >= ADV_CHIP_VER_PCI_ULTRA_3150) adv->type |= ADV_ULTRA; if (adv->chip_version == ADV_CHIP_VER_PCI_ULTRA_3050) extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_WR_EN_FILTER; else extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_SLEW_RATE; ADV_OUTB(adv, ADV_REG_IFC, extra_cfg); } if (adv_init(adv) != 0) { adv_free(adv); bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); return ENXIO; } adv->max_dma_count = ADV_PCI_MAX_DMA_COUNT; adv->max_dma_addr = ADV_PCI_MAX_DMA_ADDR; #if defined(CC_DISABLE_PCI_PARITY_INT) && CC_DISABLE_PCI_PARITY_INT { u_int16_t config_msw; config_msw = ADV_INW(adv, ADV_CONFIG_MSW); config_msw &= 0xFFC0; ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw); } #endif if (id == PCI_DEVICE_ID_ADVANSYS_1200A || id == PCI_DEVICE_ID_ADVANSYS_1200B) { adv->bug_fix_control |= ADV_BUG_FIX_IF_NOT_DWB; adv->bug_fix_control |= ADV_BUG_FIX_ASYN_USE_SYN; adv->fix_asyn_xfer = ~0; } irqrid = 0; irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irqrid, RF_SHAREABLE | RF_ACTIVE); if (irqres == NULL || bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY, NULL, adv_intr, adv, &ih)) { adv_free(adv); bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); return ENXIO; } adv_attach(adv); return 0; } static device_method_t adv_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, adv_pci_probe), DEVMETHOD(device_attach, adv_pci_attach), { 0, 0 } }; static driver_t adv_pci_driver = { "adv", adv_pci_methods, sizeof(struct adv_softc) }; static devclass_t adv_pci_devclass; DRIVER_MODULE(adv, pci, adv_pci_driver, adv_pci_devclass, 0, 0); MODULE_DEPEND(adv, pci, 1, 1, 1); diff --git a/sys/dev/advansys/adw_pci.c b/sys/dev/advansys/adw_pci.c index d9169cf70a04..9ad99bf190b4 100644 --- a/sys/dev/advansys/adw_pci.c +++ b/sys/dev/advansys/adw_pci.c @@ -1,401 +1,400 @@ /*- * Device probe and attach routines for the following * Advanced Systems Inc. SCSI controllers: * * ABP[3]940UW - Bus-Master PCI Ultra-Wide (253 CDB) * ABP950UW - Dual Channel Bus-Master PCI Ultra-Wide (253 CDB/Channel) * ABP970UW - Bus-Master PCI Ultra-Wide (253 CDB) * ABP3940U2W - Bus-Master PCI LVD/Ultra2-Wide (253 CDB) * ABP3950U2W - Bus-Master PCI LVD/Ultra2-Wide (253 CDB) * * Copyright (c) 1998, 1999, 2000 Justin Gibbs. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ADW_PCI_IOBASE PCIR_BAR(0) /* I/O Address */ #define ADW_PCI_MEMBASE PCIR_BAR(1) /* Mem I/O Address */ #define PCI_ID_ADVANSYS_3550 0x230010CD00000000ull #define PCI_ID_ADVANSYS_38C0800_REV1 0x250010CD00000000ull #define PCI_ID_ADVANSYS_38C1600_REV1 0x270010CD00000000ull #define PCI_ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull #define PCI_ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull struct adw_pci_identity; typedef int (adw_device_setup_t)(device_t, struct adw_pci_identity *, struct adw_softc *adw); struct adw_pci_identity { u_int64_t full_id; u_int64_t id_mask; char *name; adw_device_setup_t *setup; const struct adw_mcode *mcode_data; const struct adw_eeprom *default_eeprom; }; static adw_device_setup_t adw_asc3550_setup; static adw_device_setup_t adw_asc38C0800_setup; #ifdef NOTYET static adw_device_setup_t adw_asc38C1600_setup; #endif struct adw_pci_identity adw_pci_ident_table[] = { /* asc3550 based controllers */ { PCI_ID_ADVANSYS_3550, PCI_ID_DEV_VENDOR_MASK, "AdvanSys 3550 Ultra SCSI Adapter", adw_asc3550_setup, &adw_asc3550_mcode_data, &adw_asc3550_default_eeprom }, /* asc38C0800 based controllers */ { PCI_ID_ADVANSYS_38C0800_REV1, PCI_ID_DEV_VENDOR_MASK, "AdvanSys 38C0800 Ultra2 SCSI Adapter", adw_asc38C0800_setup, &adw_asc38C0800_mcode_data, &adw_asc38C0800_default_eeprom }, #ifdef NOTYET /* XXX Disabled until I have hardware to test with */ /* asc38C1600 based controllers */ { PCI_ID_ADVANSYS_38C1600_REV1, PCI_ID_DEV_VENDOR_MASK, "AdvanSys 38C1600 Ultra160 SCSI Adapter", adw_asc38C1600_setup, NULL, /* None provided by vendor thus far */ NULL /* None provided by vendor thus far */ } #endif }; static const int adw_num_pci_devs = sizeof(adw_pci_ident_table) / sizeof(*adw_pci_ident_table); #define ADW_PCI_MAX_DMA_ADDR (0xFFFFFFFFUL) #define ADW_PCI_MAX_DMA_COUNT (0xFFFFFFFFUL) static int adw_pci_probe(device_t dev); static int adw_pci_attach(device_t dev); static device_method_t adw_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, adw_pci_probe), DEVMETHOD(device_attach, adw_pci_attach), { 0, 0 } }; static driver_t adw_pci_driver = { "adw", adw_pci_methods, sizeof(struct adw_softc) }; static devclass_t adw_devclass; DRIVER_MODULE(adw, pci, adw_pci_driver, adw_devclass, 0, 0); MODULE_DEPEND(adw, pci, 1, 1, 1); static __inline u_int64_t adw_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) { u_int64_t id; id = subvendor | (subdevice << 16) | ((u_int64_t)vendor << 32) | ((u_int64_t)device << 48); return (id); } static struct adw_pci_identity * adw_find_pci_device(device_t dev) { u_int64_t full_id; struct adw_pci_identity *entry; u_int i; full_id = adw_compose_id(pci_get_device(dev), pci_get_vendor(dev), pci_get_subdevice(dev), pci_get_subvendor(dev)); for (i = 0; i < adw_num_pci_devs; i++) { entry = &adw_pci_ident_table[i]; if (entry->full_id == (full_id & entry->id_mask)) return (entry); } return (NULL); } static int adw_pci_probe(device_t dev) { struct adw_pci_identity *entry; entry = adw_find_pci_device(dev); if (entry != NULL) { device_set_desc(dev, entry->name); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int adw_pci_attach(device_t dev) { struct adw_softc *adw; struct adw_pci_identity *entry; u_int32_t command; struct resource *regs; int regs_type; int regs_id; int error; int zero; command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); entry = adw_find_pci_device(dev); if (entry == NULL) return (ENXIO); regs = NULL; regs_type = 0; regs_id = 0; #ifdef ADW_ALLOW_MEMIO if ((command & PCIM_CMD_MEMEN) != 0) { regs_type = SYS_RES_MEMORY; regs_id = ADW_PCI_MEMBASE; regs = bus_alloc_resource_any(dev, regs_type, ®s_id, RF_ACTIVE); } #endif if (regs == NULL && (command & PCIM_CMD_PORTEN) != 0) { regs_type = SYS_RES_IOPORT; regs_id = ADW_PCI_IOBASE; regs = bus_alloc_resource_any(dev, regs_type, ®s_id, RF_ACTIVE); } if (regs == NULL) { device_printf(dev, "can't allocate register resources\n"); return (ENOMEM); } adw = adw_alloc(dev, regs, regs_type, regs_id); if (adw == NULL) return(ENOMEM); /* * Now that we have access to our registers, just verify that * this really is an AdvanSys device. */ if (adw_find_signature(adw) == 0) { adw_free(adw); return (ENXIO); } adw_reset_chip(adw); error = entry->setup(dev, entry, adw); if (error != 0) return (error); /* Ensure busmastering is enabled */ command |= PCIM_CMD_BUSMASTEREN; pci_write_config(dev, PCIR_COMMAND, command, /*bytes*/1); /* Allocate a dmatag for our transfer DMA maps */ - /* XXX Should be a child of the PCI bus dma tag */ error = bus_dma_tag_create( /* parent */ bus_get_dma_tag(dev), /* alignment */ 1, /* boundary */ 0, /* lowaddr */ ADW_PCI_MAX_DMA_ADDR, /* highaddr */ BUS_SPACE_MAXADDR, /* filter */ NULL, /* filterarg */ NULL, /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, /* nsegments */ ~0, /* maxsegsz */ ADW_PCI_MAX_DMA_COUNT, /* flags */ 0, /* lockfunc */ busdma_lock_mutex, /* lockarg */ &Giant, &adw->parent_dmat); adw->init_level++; if (error != 0) { printf("%s: Could not allocate DMA tag - error %d\n", adw_name(adw), error); adw_free(adw); return (error); } adw->init_level++; error = adw_init(adw); if (error != 0) { adw_free(adw); return (error); } /* * If the PCI Configuration Command Register "Parity Error Response * Control" Bit was clear (0), then set the microcode variable * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode * to ignore DMA parity errors. */ if ((command & PCIM_CMD_PERRESPEN) == 0) adw_lram_write_16(adw, ADW_MC_CONTROL_FLAG, adw_lram_read_16(adw, ADW_MC_CONTROL_FLAG) | ADW_MC_CONTROL_IGN_PERR); zero = 0; adw->irq_res_type = SYS_RES_IRQ; adw->irq = bus_alloc_resource_any(dev, adw->irq_res_type, &zero, RF_ACTIVE | RF_SHAREABLE); if (adw->irq == NULL) { adw_free(adw); return (ENOMEM); } error = adw_attach(adw); if (error != 0) adw_free(adw); return (error); } static int adw_generic_setup(device_t dev, struct adw_pci_identity *entry, struct adw_softc *adw) { adw->channel = pci_get_function(dev) == 1 ? 'B' : 'A'; adw->chip = ADW_CHIP_NONE; adw->features = ADW_FENONE; adw->flags = ADW_FNONE; adw->mcode_data = entry->mcode_data; adw->default_eeprom = entry->default_eeprom; return (0); } static int adw_asc3550_setup(device_t dev, struct adw_pci_identity *entry, struct adw_softc *adw) { int error; error = adw_generic_setup(dev, entry, adw); if (error != 0) return (error); adw->chip = ADW_CHIP_ASC3550; adw->features = ADW_ASC3550_FE; adw->memsize = ADW_3550_MEMSIZE; /* * For ASC-3550, setting the START_CTL_EMFU [3:2] bits * sets a FIFO threshold of 128 bytes. This register is * only accessible to the host. */ adw_outb(adw, ADW_DMA_CFG0, ADW_DMA_CFG0_START_CTL_EM_FU|ADW_DMA_CFG0_READ_CMD_MRM); adw_outb(adw, ADW_MEM_CFG, adw_inb(adw, ADW_MEM_CFG) | ADW_MEM_CFG_RAM_SZ_8KB); return (0); } static int adw_asc38C0800_setup(device_t dev, struct adw_pci_identity *entry, struct adw_softc *adw) { int error; error = adw_generic_setup(dev, entry, adw); if (error != 0) return (error); /* * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and * START_CTL_TH [3:2] bits for the default FIFO threshold. * * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes. * * For DMA Errata #4 set the BC_THRESH_ENB bit. */ adw_outb(adw, ADW_DMA_CFG0, ADW_DMA_CFG0_BC_THRESH_ENB|ADW_DMA_CFG0_FIFO_THRESH_80B |ADW_DMA_CFG0_START_CTL_TH|ADW_DMA_CFG0_READ_CMD_MRM); adw_outb(adw, ADW_MEM_CFG, adw_inb(adw, ADW_MEM_CFG) | ADW_MEM_CFG_RAM_SZ_16KB); adw->chip = ADW_CHIP_ASC38C0800; adw->features = ADW_ASC38C0800_FE; adw->memsize = ADW_38C0800_MEMSIZE; return (error); } #ifdef NOTYET static int adw_asc38C1600_setup(device_t dev, struct adw_pci_identity *entry, struct adw_softc *adw) { int error; error = adw_generic_setup(dev, entry, adw); if (error != 0) return (error); adw->chip = ADW_CHIP_ASC38C1600; adw->features = ADW_ASC38C1600_FE; adw->memsize = ADW_38C1600_MEMSIZE; return (error); } #endif diff --git a/sys/dev/aic7xxx/ahc_eisa.c b/sys/dev/aic7xxx/ahc_eisa.c index 8c6e4df444d8..05d262bbc72e 100644 --- a/sys/dev/aic7xxx/ahc_eisa.c +++ b/sys/dev/aic7xxx/ahc_eisa.c @@ -1,179 +1,178 @@ /*- * FreeBSD, EISA product support functions * * * Copyright (c) 1994-1998, 2000, 2001 Justin T. Gibbs. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice immediately at the beginning of the file, without modification, * this list of conditions, and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahc_eisa.c#13 $ */ #include __FBSDID("$FreeBSD$"); #include #include static int aic7770_probe(device_t dev) { struct aic7770_identity *entry; struct resource *regs; uint32_t iobase; bus_space_handle_t bsh; bus_space_tag_t tag; u_int irq; u_int intdef; u_int hcntrl; int shared; int rid; int error; entry = aic7770_find_device(eisa_get_id(dev)); if (entry == NULL) return (ENXIO); device_set_desc(dev, entry->name); iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) + AHC_EISA_SLOT_OFFSET; eisa_add_iospace(dev, iobase, AHC_EISA_IOSIZE, RESVADDR_NONE); rid = 0; regs = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); if (regs == NULL) { device_printf(dev, "Unable to map I/O space?!\n"); return ENOMEM; } tag = rman_get_bustag(regs); bsh = rman_get_bushandle(regs); error = 0; /* Pause the card preseving the IRQ type */ hcntrl = bus_space_read_1(tag, bsh, HCNTRL) & IRQMS; bus_space_write_1(tag, bsh, HCNTRL, hcntrl | PAUSE); while ((bus_space_read_1(tag, bsh, HCNTRL) & PAUSE) == 0) ; /* Make sure we have a valid interrupt vector */ intdef = bus_space_read_1(tag, bsh, INTDEF); shared = (intdef & EDGE_TRIG) ? EISA_TRIGGER_EDGE : EISA_TRIGGER_LEVEL; irq = intdef & VECTOR; switch (irq) { case 9: case 10: case 11: case 12: case 14: case 15: break; default: printf("aic7770 at slot %d: illegal irq setting %d\n", eisa_get_slot(dev), intdef); error = ENXIO; } if (error == 0) eisa_add_intr(dev, irq, shared); bus_release_resource(dev, SYS_RES_IOPORT, rid, regs); return (error); } static int aic7770_attach(device_t dev) { struct aic7770_identity *entry; struct ahc_softc *ahc; char *name; int error; entry = aic7770_find_device(eisa_get_id(dev)); if (entry == NULL) return (ENXIO); /* * Allocate a softc for this card and * set it up for attachment by our * common detect routine. */ name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT); if (name == NULL) return (ENOMEM); strcpy(name, device_get_nameunit(dev)); ahc = ahc_alloc(dev, name); if (ahc == NULL) return (ENOMEM); ahc_set_unit(ahc, device_get_unit(dev)); /* Allocate a dmatag for our SCB DMA maps */ - /* XXX Should be a child of the PCI bus dma tag */ error = aic_dma_tag_create(ahc, /*parent*/bus_get_dma_tag(dev), /*alignment*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, /*nsegments*/AHC_NSEG, /*maxsegsz*/AHC_MAXTRANSFER_SIZE, /*flags*/0, &ahc->parent_dmat); if (error != 0) { printf("ahc_eisa_attach: Could not allocate DMA tag " "- error %d\n", error); ahc_free(ahc); return (ENOMEM); } ahc->dev_softc = dev; error = aic7770_config(ahc, entry, /*unused ioport arg*/0); if (error != 0) { ahc_free(ahc); return (error); } ahc_attach(ahc); return (0); } static device_method_t ahc_eisa_device_methods[] = { /* Device interface */ DEVMETHOD(device_probe, aic7770_probe), DEVMETHOD(device_attach, aic7770_attach), DEVMETHOD(device_detach, ahc_detach), { 0, 0 } }; static driver_t ahc_eisa_driver = { "ahc", ahc_eisa_device_methods, sizeof(struct ahc_softc) }; DRIVER_MODULE(ahc_eisa, eisa, ahc_eisa_driver, ahc_devclass, 0, 0); MODULE_DEPEND(ahc_eisa, ahc, 1, 1, 1); MODULE_VERSION(ahc_eisa, 1); diff --git a/sys/dev/aic7xxx/ahc_isa.c b/sys/dev/aic7xxx/ahc_isa.c index 0bf0f537274e..c73e85c3d551 100644 --- a/sys/dev/aic7xxx/ahc_isa.c +++ b/sys/dev/aic7xxx/ahc_isa.c @@ -1,302 +1,301 @@ /*- * FreeBSD, VLB/ISA product support functions * * Copyright (c) 2004 Justin T. Gibbs. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * substantially similar to the "NO WARRANTY" disclaimer below * ("Disclaimer") and any redistribution must be conditioned upon * including a substantially similar Disclaimer requirement for further * binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names * of any contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * $Id$ */ #include __FBSDID("$FreeBSD$"); #include #include /* For CHAR_BIT*/ #include /* For ISA attach glue */ static struct aic7770_identity *ahc_isa_find_device(bus_space_tag_t tag, bus_space_handle_t bsh); static void ahc_isa_identify(driver_t *driver, device_t parent); static int ahc_isa_probe(device_t dev); static int ahc_isa_attach(device_t dev); /* * Perform an EISA probe of the address with the addition * of a "priming" step. The 284X requires priming (a write * to offset 0x80, the first EISA ID register) to ensure it * is not mistaken as an EISA card. Once we have the ID, * lookup the controller in the aic7770 table of supported * devices. */ static struct aic7770_identity * ahc_isa_find_device(bus_space_tag_t tag, bus_space_handle_t bsh) { uint32_t id; u_int id_size; int i; id = 0; id_size = sizeof(id); for (i = 0; i < id_size; i++) { bus_space_write_1(tag, bsh, 0x80, 0x80 + i); id |= bus_space_read_1(tag, bsh, 0x80 + i) << ((id_size - i - 1) * CHAR_BIT); } return (aic7770_find_device(id)); } static void ahc_isa_identify(driver_t *driver, device_t parent) { int slot; int max_slot; max_slot = 14; for (slot = 0; slot <= max_slot; slot++) { struct aic7770_identity *entry; bus_space_tag_t tag; bus_space_handle_t bsh; struct resource *regs; uint32_t iobase; int rid; rid = 0; iobase = (slot * AHC_EISA_SLOT_SIZE) + AHC_EISA_SLOT_OFFSET; regs = bus_alloc_resource(parent, SYS_RES_IOPORT, &rid, iobase, iobase, AHC_EISA_IOSIZE, RF_ACTIVE); if (regs == NULL) { if (bootverbose) printf("ahc_isa_probe %d: ioport 0x%x " "alloc failed\n", slot, iobase); continue; } tag = rman_get_bustag(regs); bsh = rman_get_bushandle(regs); entry = ahc_isa_find_device(tag, bsh); if (entry != NULL) { device_t child; child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ahc", -1); if (child != NULL) { device_set_driver(child, driver); bus_set_resource(child, SYS_RES_IOPORT, 0, iobase, AHC_EISA_IOSIZE); } } bus_release_resource(parent, SYS_RES_IOPORT, rid, regs); } } static int ahc_isa_probe(device_t dev) { struct aic7770_identity *entry; bus_space_tag_t tag; bus_space_handle_t bsh; struct resource *regs; struct resource *irq; uint32_t iobase; u_int intdef; u_int hcntrl; int irq_num; int error; int zero; error = ENXIO; zero = 0; regs = NULL; irq = NULL; /* Skip probes for ISA PnP devices */ if (isa_get_logicalid(dev) != 0) return (error); regs = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &zero, RF_ACTIVE); if (regs == NULL) { device_printf(dev, "No resources allocated.\n"); return (ENOMEM); } iobase = rman_get_start(regs); tag = rman_get_bustag(regs); bsh = rman_get_bushandle(regs); entry = ahc_isa_find_device(tag, bsh); if (entry == NULL) goto cleanup; /* Pause the card preseving the IRQ type */ hcntrl = bus_space_read_1(tag, bsh, HCNTRL) & IRQMS; bus_space_write_1(tag, bsh, HCNTRL, hcntrl | PAUSE); while ((bus_space_read_1(tag, bsh, HCNTRL) & PAUSE) == 0) ; /* Make sure we have a valid interrupt vector */ intdef = bus_space_read_1(tag, bsh, INTDEF); irq_num = intdef & VECTOR; switch (irq_num) { case 9: case 10: case 11: case 12: case 14: case 15: break; default: device_printf(dev, "@0x%x: illegal irq setting %d\n", iobase, irq_num); goto cleanup; } if (bus_set_resource(dev, SYS_RES_IRQ, zero, irq_num, 1) != 0) goto cleanup; /* * The 284X only supports edge triggered interrupts, * so do not claim RF_SHAREABLE. */ irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &zero, 0 /*!(RF_ACTIVE|RF_SHAREABLE)*/); if (irq != NULL) { error = 0; device_set_desc(dev, entry->name); } else device_printf(dev, "@0x%x: irq %d allocation failed\n", iobase, irq_num); cleanup: if (regs != NULL) { bus_release_resource(dev, SYS_RES_IOPORT, zero, regs); regs = NULL; } if (irq != NULL) { bus_release_resource(dev, SYS_RES_IRQ, zero, irq); irq = NULL; } return (error); } static int ahc_isa_attach(device_t dev) { struct aic7770_identity *entry; bus_space_tag_t tag; bus_space_handle_t bsh; struct resource *regs; struct ahc_softc *ahc; char *name; int zero; int error; zero = 0; regs = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &zero, RF_ACTIVE); if (regs == NULL) return (ENOMEM); tag = rman_get_bustag(regs); bsh = rman_get_bushandle(regs); entry = ahc_isa_find_device(tag, bsh); bus_release_resource(dev, SYS_RES_IOPORT, zero, regs); if (entry == NULL) return (ENODEV); /* * Allocate a softc for this card and * set it up for attachment by our * common detect routine. */ name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT); if (name == NULL) return (ENOMEM); strcpy(name, device_get_nameunit(dev)); ahc = ahc_alloc(dev, name); if (ahc == NULL) return (ENOMEM); ahc_set_unit(ahc, device_get_unit(dev)); /* Allocate a dmatag for our SCB DMA maps */ - /* XXX Should be a child of the VLB/ISA bus dma tag */ error = aic_dma_tag_create(ahc, /*parent*/bus_get_dma_tag(dev), /*alignment*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, /*nsegments*/AHC_NSEG, /*maxsegsz*/AHC_MAXTRANSFER_SIZE, /*flags*/0, &ahc->parent_dmat); if (error != 0) { printf("ahc_isa_attach: Could not allocate DMA tag " "- error %d\n", error); ahc_free(ahc); return (ENOMEM); } ahc->dev_softc = dev; error = aic7770_config(ahc, entry, /*unused ioport arg*/0); if (error != 0) { ahc_free(ahc); return (error); } ahc_attach(ahc); return (0); } static device_method_t ahc_isa_device_methods[] = { /* Device interface */ DEVMETHOD(device_identify, ahc_isa_identify), DEVMETHOD(device_probe, ahc_isa_probe), DEVMETHOD(device_attach, ahc_isa_attach), DEVMETHOD(device_detach, ahc_detach), { 0, 0 } }; static driver_t ahc_isa_driver = { "ahc", ahc_isa_device_methods, sizeof(struct ahc_softc) }; DRIVER_MODULE(ahc_isa, isa, ahc_isa_driver, ahc_devclass, 0, 0); MODULE_DEPEND(ahc_isa, ahc, 1, 1, 1); MODULE_VERSION(ahc_isa, 1); diff --git a/sys/dev/aic7xxx/ahc_pci.c b/sys/dev/aic7xxx/ahc_pci.c index 9a27aaf9f766..2392298661bb 100644 --- a/sys/dev/aic7xxx/ahc_pci.c +++ b/sys/dev/aic7xxx/ahc_pci.c @@ -1,238 +1,237 @@ /*- * FreeBSD, PCI product support functions * * Copyright (c) 1995-2001 Justin T. Gibbs * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU Public License ("GPL"). * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahc_pci.c#19 $ */ #include __FBSDID("$FreeBSD$"); #include static int ahc_pci_probe(device_t dev); static int ahc_pci_attach(device_t dev); static device_method_t ahc_pci_device_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ahc_pci_probe), DEVMETHOD(device_attach, ahc_pci_attach), DEVMETHOD(device_detach, ahc_detach), { 0, 0 } }; static driver_t ahc_pci_driver = { "ahc", ahc_pci_device_methods, sizeof(struct ahc_softc) }; DRIVER_MODULE(ahc_pci, pci, ahc_pci_driver, ahc_devclass, 0, 0); MODULE_DEPEND(ahc_pci, ahc, 1, 1, 1); MODULE_VERSION(ahc_pci, 1); static int ahc_pci_probe(device_t dev) { struct ahc_pci_identity *entry; entry = ahc_find_pci_device(dev); if (entry != NULL) { device_set_desc(dev, entry->name); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int ahc_pci_attach(device_t dev) { struct ahc_pci_identity *entry; struct ahc_softc *ahc; char *name; int error; entry = ahc_find_pci_device(dev); if (entry == NULL) return (ENXIO); /* * Allocate a softc for this card and * set it up for attachment by our * common detect routine. */ name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT); if (name == NULL) return (ENOMEM); strcpy(name, device_get_nameunit(dev)); ahc = ahc_alloc(dev, name); if (ahc == NULL) return (ENOMEM); ahc_set_unit(ahc, device_get_unit(dev)); /* * Should we bother disabling 39Bit addressing * based on installed memory? */ if (sizeof(bus_addr_t) > 4) ahc->flags |= AHC_39BIT_ADDRESSING; /* Allocate a dmatag for our SCB DMA maps */ - /* XXX Should be a child of the PCI bus dma tag */ error = aic_dma_tag_create(ahc, /*parent*/bus_get_dma_tag(dev), /*alignment*/1, /*boundary*/0, (ahc->flags & AHC_39BIT_ADDRESSING) ? 0x7FFFFFFFFFLL : BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, /*nsegments*/AHC_NSEG, /*maxsegsz*/AHC_MAXTRANSFER_SIZE, /*flags*/0, &ahc->parent_dmat); if (error != 0) { printf("ahc_pci_attach: Could not allocate DMA tag " "- error %d\n", error); ahc_free(ahc); return (ENOMEM); } ahc->dev_softc = dev; error = ahc_pci_config(ahc, entry); if (error != 0) { ahc_free(ahc); return (error); } ahc_attach(ahc); return (0); } int ahc_pci_map_registers(struct ahc_softc *ahc) { struct resource *regs; u_int command; int regs_type; int regs_id; int allow_memio; command = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); regs = NULL; regs_type = 0; regs_id = 0; /* Retrieve the per-device 'allow_memio' hint */ if (resource_int_value(device_get_name(ahc->dev_softc), device_get_unit(ahc->dev_softc), "allow_memio", &allow_memio) != 0) { if (bootverbose) device_printf(ahc->dev_softc, "Defaulting to MEMIO "); #ifdef AHC_ALLOW_MEMIO if (bootverbose) printf("on\n"); allow_memio = 1; #else if (bootverbose) printf("off\n"); allow_memio = 0; #endif } if ((allow_memio != 0) && (command & PCIM_CMD_MEMEN) != 0) { regs_type = SYS_RES_MEMORY; regs_id = AHC_PCI_MEMADDR; regs = bus_alloc_resource_any(ahc->dev_softc, regs_type, ®s_id, RF_ACTIVE); if (regs != NULL) { ahc->tag = rman_get_bustag(regs); ahc->bsh = rman_get_bushandle(regs); /* * Do a quick test to see if memory mapped * I/O is functioning correctly. */ if (ahc_pci_test_register_access(ahc) != 0) { device_printf(ahc->dev_softc, "PCI Device %d:%d:%d failed memory " "mapped test. Using PIO.\n", aic_get_pci_bus(ahc->dev_softc), aic_get_pci_slot(ahc->dev_softc), aic_get_pci_function(ahc->dev_softc)); bus_release_resource(ahc->dev_softc, regs_type, regs_id, regs); regs = NULL; } else { command &= ~PCIM_CMD_PORTEN; aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/1); } } } if (regs == NULL && (command & PCIM_CMD_PORTEN) != 0) { regs_type = SYS_RES_IOPORT; regs_id = AHC_PCI_IOADDR; regs = bus_alloc_resource_any(ahc->dev_softc, regs_type, ®s_id, RF_ACTIVE); if (regs != NULL) { ahc->tag = rman_get_bustag(regs); ahc->bsh = rman_get_bushandle(regs); if (ahc_pci_test_register_access(ahc) != 0) { device_printf(ahc->dev_softc, "PCI Device %d:%d:%d failed I/O " "mapped test.\n", aic_get_pci_bus(ahc->dev_softc), aic_get_pci_slot(ahc->dev_softc), aic_get_pci_function(ahc->dev_softc)); bus_release_resource(ahc->dev_softc, regs_type, regs_id, regs); regs = NULL; } else { command &= ~PCIM_CMD_MEMEN; aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/1); } } } if (regs == NULL) { device_printf(ahc->dev_softc, "can't allocate register resources\n"); return (ENOMEM); } ahc->platform_data->regs_res_type = regs_type; ahc->platform_data->regs_res_id = regs_id; ahc->platform_data->regs = regs; return (0); } diff --git a/sys/dev/aic7xxx/ahd_pci.c b/sys/dev/aic7xxx/ahd_pci.c index 3a0116160083..0c06673ca514 100644 --- a/sys/dev/aic7xxx/ahd_pci.c +++ b/sys/dev/aic7xxx/ahd_pci.c @@ -1,263 +1,262 @@ /*- * FreeBSD, PCI product support functions * * Copyright (c) 1995-2001 Justin T. Gibbs * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU Public License ("GPL"). * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahd_pci.c#17 $ */ #include __FBSDID("$FreeBSD$"); #include static int ahd_pci_probe(device_t dev); static int ahd_pci_attach(device_t dev); static device_method_t ahd_pci_device_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ahd_pci_probe), DEVMETHOD(device_attach, ahd_pci_attach), DEVMETHOD(device_detach, ahd_detach), { 0, 0 } }; static driver_t ahd_pci_driver = { "ahd", ahd_pci_device_methods, sizeof(struct ahd_softc) }; static devclass_t ahd_devclass; DRIVER_MODULE(ahd, pci, ahd_pci_driver, ahd_devclass, 0, 0); MODULE_DEPEND(ahd_pci, ahd, 1, 1, 1); MODULE_VERSION(ahd_pci, 1); static int ahd_pci_probe(device_t dev) { struct ahd_pci_identity *entry; entry = ahd_find_pci_device(dev); if (entry != NULL) { device_set_desc(dev, entry->name); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int ahd_pci_attach(device_t dev) { struct ahd_pci_identity *entry; struct ahd_softc *ahd; char *name; int error; entry = ahd_find_pci_device(dev); if (entry == NULL) return (ENXIO); /* * Allocate a softc for this card and * set it up for attachment by our * common detect routine. */ name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT); if (name == NULL) return (ENOMEM); strcpy(name, device_get_nameunit(dev)); ahd = ahd_alloc(dev, name); if (ahd == NULL) return (ENOMEM); ahd_set_unit(ahd, device_get_unit(dev)); /* * Should we bother disabling 39Bit addressing * based on installed memory? */ if (sizeof(bus_addr_t) > 4) ahd->flags |= AHD_39BIT_ADDRESSING; /* Allocate a dmatag for our SCB DMA maps */ - /* XXX Should be a child of the PCI bus dma tag */ error = aic_dma_tag_create(ahd, /*parent*/bus_get_dma_tag(dev), /*alignment*/1, /*boundary*/0, (ahd->flags & AHD_39BIT_ADDRESSING) ? 0x7FFFFFFFFF : BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, /*nsegments*/AHD_NSEG, /*maxsegsz*/AHD_MAXTRANSFER_SIZE, /*flags*/0, &ahd->parent_dmat); if (error != 0) { printf("ahd_pci_attach: Could not allocate DMA tag " "- error %d\n", error); ahd_free(ahd); return (ENOMEM); } ahd->dev_softc = dev; error = ahd_pci_config(ahd, entry); if (error != 0) { ahd_free(ahd); return (error); } ahd_sysctl(ahd); ahd_attach(ahd); return (0); } int ahd_pci_map_registers(struct ahd_softc *ahd) { struct resource *regs; struct resource *regs2; u_int command; int regs_type; int regs_id; int regs_id2; int allow_memio; command = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1); regs = NULL; regs2 = NULL; regs_type = 0; regs_id = 0; /* Retrieve the per-device 'allow_memio' hint */ if (resource_int_value(device_get_name(ahd->dev_softc), device_get_unit(ahd->dev_softc), "allow_memio", &allow_memio) != 0) { if (bootverbose) device_printf(ahd->dev_softc, "Defaulting to MEMIO on\n"); allow_memio = 1; } if ((command & PCIM_CMD_MEMEN) != 0 && (ahd->bugs & AHD_PCIX_MMAPIO_BUG) == 0 && allow_memio != 0) { regs_type = SYS_RES_MEMORY; regs_id = AHD_PCI_MEMADDR; regs = bus_alloc_resource_any(ahd->dev_softc, regs_type, ®s_id, RF_ACTIVE); if (regs != NULL) { int error; ahd->tags[0] = rman_get_bustag(regs); ahd->bshs[0] = rman_get_bushandle(regs); ahd->tags[1] = ahd->tags[0]; error = bus_space_subregion(ahd->tags[0], ahd->bshs[0], /*offset*/0x100, /*size*/0x100, &ahd->bshs[1]); /* * Do a quick test to see if memory mapped * I/O is functioning correctly. */ if (error != 0 || ahd_pci_test_register_access(ahd) != 0) { device_printf(ahd->dev_softc, "PCI Device %d:%d:%d failed memory " "mapped test. Using PIO.\n", aic_get_pci_bus(ahd->dev_softc), aic_get_pci_slot(ahd->dev_softc), aic_get_pci_function(ahd->dev_softc)); bus_release_resource(ahd->dev_softc, regs_type, regs_id, regs); regs = NULL; AHD_CORRECTABLE_ERROR(ahd); } else { command &= ~PCIM_CMD_PORTEN; aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/1); } } } if (regs == NULL && (command & PCIM_CMD_PORTEN) != 0) { regs_type = SYS_RES_IOPORT; regs_id = AHD_PCI_IOADDR0; regs = bus_alloc_resource_any(ahd->dev_softc, regs_type, ®s_id, RF_ACTIVE); if (regs == NULL) { device_printf(ahd->dev_softc, "can't allocate register resources\n"); AHD_UNCORRECTABLE_ERROR(ahd); return (ENOMEM); } ahd->tags[0] = rman_get_bustag(regs); ahd->bshs[0] = rman_get_bushandle(regs); /* And now the second BAR */ regs_id2 = AHD_PCI_IOADDR1; regs2 = bus_alloc_resource_any(ahd->dev_softc, regs_type, ®s_id2, RF_ACTIVE); if (regs2 == NULL) { device_printf(ahd->dev_softc, "can't allocate register resources\n"); AHD_UNCORRECTABLE_ERROR(ahd); return (ENOMEM); } ahd->tags[1] = rman_get_bustag(regs2); ahd->bshs[1] = rman_get_bushandle(regs2); command &= ~PCIM_CMD_MEMEN; aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/1); ahd->platform_data->regs_res_type[1] = regs_type; ahd->platform_data->regs_res_id[1] = regs_id2; ahd->platform_data->regs[1] = regs2; } ahd->platform_data->regs_res_type[0] = regs_type; ahd->platform_data->regs_res_id[0] = regs_id; ahd->platform_data->regs[0] = regs; return (0); } int ahd_pci_map_int(struct ahd_softc *ahd) { int zero; zero = 0; ahd->platform_data->irq = bus_alloc_resource_any(ahd->dev_softc, SYS_RES_IRQ, &zero, RF_ACTIVE | RF_SHAREABLE); if (ahd->platform_data->irq == NULL) return (ENOMEM); ahd->platform_data->irq_res_type = SYS_RES_IRQ; return (ahd_map_int(ahd)); } diff --git a/sys/dev/buslogic/bt_pci.c b/sys/dev/buslogic/bt_pci.c index 5994bec2119c..6e03a97c5d45 100644 --- a/sys/dev/buslogic/bt_pci.c +++ b/sys/dev/buslogic/bt_pci.c @@ -1,238 +1,237 @@ /*- * Product specific probe and attach routines for: * Buslogic BT946, BT948, BT956, BT958 SCSI controllers * * Copyright (c) 1995, 1997, 1998 Justin T. Gibbs * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #define BT_PCI_IOADDR PCIR_BAR(0) #define BT_PCI_MEMADDR PCIR_BAR(1) #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040104Bul #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140104Bul #define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130104Bul static int bt_pci_alloc_resources(device_t dev) { int command, type = 0, rid, zero; struct resource *regs = 0; struct resource *irq = 0; command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); #if 0 /* XXX Memory Mapped I/O seems to cause problems */ if (command & PCIM_CMD_MEMEN) { type = SYS_RES_MEMORY; rid = BT_PCI_MEMADDR; regs = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE); } #else if (!regs && (command & PCIM_CMD_PORTEN)) { type = SYS_RES_IOPORT; rid = BT_PCI_IOADDR; regs = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE); } #endif if (!regs) return (ENOMEM); zero = 0; irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &zero, RF_ACTIVE | RF_SHAREABLE); if (!irq) { bus_release_resource(dev, type, rid, regs); return (ENOMEM); } bt_init_softc(dev, regs, irq, 0); return (0); } static void bt_pci_release_resources(device_t dev) { struct bt_softc *bt = device_get_softc(dev); if (bt->port) /* XXX can't cope with memory registers anyway */ bus_release_resource(dev, SYS_RES_IOPORT, BT_PCI_IOADDR, bt->port); if (bt->irq) bus_release_resource(dev, SYS_RES_IRQ, 0, bt->irq); bt_free_softc(dev); } static int bt_pci_probe(device_t dev) { switch (pci_get_devid(dev)) { case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER: case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC: { struct bt_softc *bt = device_get_softc(dev); pci_info_data_t pci_info; int error; error = bt_pci_alloc_resources(dev); if (error) return (error); /* * Determine if an ISA compatible I/O port has been * enabled. If so, record the port so it will not * be probed by our ISA probe. If the PCI I/O port * was not set to the compatibility port, disable it. */ error = bt_cmd(bt, BOP_INQUIRE_PCI_INFO, /*param*/NULL, /*paramlen*/0, (u_int8_t*)&pci_info, sizeof(pci_info), DEFAULT_CMD_TIMEOUT); if (error == 0 && pci_info.io_port < BIO_DISABLED) { bt_mark_probed_bio(pci_info.io_port); if (rman_get_start(bt->port) != bt_iop_from_bio(pci_info.io_port)) { u_int8_t new_addr; new_addr = BIO_DISABLED; bt_cmd(bt, BOP_MODIFY_IO_ADDR, /*param*/&new_addr, /*paramlen*/1, /*reply_buf*/NULL, /*reply_len*/0, DEFAULT_CMD_TIMEOUT); } } bt_pci_release_resources(dev); device_set_desc(dev, "Buslogic Multi-Master SCSI Host Adapter"); return (0); } default: break; } return (ENXIO); } static int bt_pci_attach(device_t dev) { struct bt_softc *bt = device_get_softc(dev); int opri; int error; /* Initialize softc */ error = bt_pci_alloc_resources(dev); if (error) { device_printf(dev, "can't allocate resources in bt_pci_attach\n"); return error; } /* Allocate a dmatag for our CCB DMA maps */ - /* XXX Should be a child of the PCI bus dma tag */ if (bus_dma_tag_create( /* PCI parent */ bus_get_dma_tag(dev), /* alignemnt */ 1, /* boundary */ 0, /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, /* highaddr */ BUS_SPACE_MAXADDR, /* filter */ NULL, /* filterarg */ NULL, /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, /* nsegments */ ~0, /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, /* flags */ 0, /* lockfunc */ busdma_lock_mutex, /* lockarg */ &Giant, &bt->parent_dmat) != 0) { bt_pci_release_resources(dev); return (ENOMEM); } /* * Protect ourself from spurrious interrupts during * intialization and attach. We should really rely * on interrupts during attach, but we don't have * access to our interrupts during ISA probes, so until * that changes, we mask our interrupts during attach * too. */ opri = splcam(); if (bt_probe(dev) || bt_fetch_adapter_info(dev) || bt_init(dev)) { bt_pci_release_resources(dev); splx(opri); return (ENXIO); } error = bt_attach(dev); splx(opri); if (error) { bt_pci_release_resources(dev); return (error); } return (0); } static device_method_t bt_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, bt_pci_probe), DEVMETHOD(device_attach, bt_pci_attach), { 0, 0 } }; static driver_t bt_pci_driver = { "bt", bt_pci_methods, sizeof(struct bt_softc), }; static devclass_t bt_devclass; DRIVER_MODULE(bt, pci, bt_pci_driver, bt_devclass, 0, 0); MODULE_DEPEND(bt, pci, 1, 1, 1); diff --git a/sys/dev/dpt/dpt_pci.c b/sys/dev/dpt/dpt_pci.c index 2009dbdf2f20..0003e9986b82 100644 --- a/sys/dev/dpt/dpt_pci.c +++ b/sys/dev/dpt/dpt_pci.c @@ -1,200 +1,199 @@ /*- * Copyright (c) 2000 Matthew N. Dodd * All rights reserved. * * Copyright (c) 1997 Simon Shapiro * All Rights Reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DPT_VENDOR_ID 0x1044 #define DPT_DEVICE_ID 0xa400 #define DPT_PCI_IOADDR PCIR_BAR(0) /* I/O Address */ #define DPT_PCI_MEMADDR PCIR_BAR(1) /* Mem I/O Address */ #define ISA_PRIMARY_WD_ADDRESS 0x1f8 static int dpt_pci_probe (device_t); static int dpt_pci_attach (device_t); static int dpt_pci_probe (device_t dev) { if ((pci_get_vendor(dev) == DPT_VENDOR_ID) && (pci_get_device(dev) == DPT_DEVICE_ID)) { device_set_desc(dev, "DPT Caching SCSI RAID Controller"); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int dpt_pci_attach (device_t dev) { dpt_softc_t * dpt; int s; int error = 0; u_int32_t command; dpt = device_get_softc(dev); dpt->dev = dev; command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); #ifdef DPT_ALLOW_MMIO if ((command & PCIM_CMD_MEMEN) != 0) { dpt->io_rid = DPT_PCI_MEMADDR; dpt->io_type = SYS_RES_MEMORY; dpt->io_res = bus_alloc_resource_any(dev, dpt->io_type, &dpt->io_rid, RF_ACTIVE); } #endif if (dpt->io_res == NULL && (command & PCIM_CMD_PORTEN) != 0) { dpt->io_rid = DPT_PCI_IOADDR; dpt->io_type = SYS_RES_IOPORT; dpt->io_res = bus_alloc_resource_any(dev, dpt->io_type, &dpt->io_rid, RF_ACTIVE); } if (dpt->io_res == NULL) { device_printf(dev, "can't allocate register resources\n"); error = ENOMEM; goto bad; } dpt->io_offset = 0x10; dpt->irq_rid = 0; dpt->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &dpt->irq_rid, RF_ACTIVE | RF_SHAREABLE); if (dpt->irq_res == NULL) { device_printf(dev, "No irq?!\n"); error = ENOMEM; goto bad; } /* Ensure busmastering is enabled */ command |= PCIM_CMD_BUSMASTEREN; pci_write_config(dev, PCIR_COMMAND, command, /*bytes*/1); if (rman_get_start(dpt->io_res) == (ISA_PRIMARY_WD_ADDRESS - 0x10)) { #ifdef DPT_DEBUG_WARN device_printf(dev, "Mapped as an IDE controller. " "Disabling SCSI setup\n"); #endif error = ENXIO; goto bad; } dpt_alloc(dev); /* Allocate a dmatag representing the capabilities of this attachment */ - /* XXX Should be a child of the PCI bus dma tag */ if (bus_dma_tag_create( /* PCI parent */ bus_get_dma_tag(dev), /* alignemnt */ 1, /* boundary */ 0, /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, /* highaddr */ BUS_SPACE_MAXADDR, /* filter */ NULL, /* filterarg */ NULL, /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, /* nsegments */ ~0, /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, /* flags */ 0, /* lockfunc */ busdma_lock_mutex, /* lockarg */ &Giant, &dpt->parent_dmat) != 0) { error = ENXIO; goto bad; } s = splcam(); if (dpt_init(dpt) != 0) { error = ENXIO; goto bad; } /* Register with the XPT */ dpt_attach(dpt); splx(s); if (bus_setup_intr(dev, dpt->irq_res, INTR_TYPE_CAM | INTR_ENTROPY, NULL, dpt_intr, dpt, &dpt->ih)) { device_printf(dev, "Unable to register interrupt handler\n"); error = ENXIO; goto bad; } return (error); bad: dpt_release_resources(dev); dpt_free(dpt); return (error); } static device_method_t dpt_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, dpt_pci_probe), DEVMETHOD(device_attach, dpt_pci_attach), DEVMETHOD(device_detach, dpt_detach), { 0, 0 } }; static driver_t dpt_pci_driver = { "dpt", dpt_pci_methods, sizeof(dpt_softc_t), }; DRIVER_MODULE(dpt, pci, dpt_pci_driver, dpt_devclass, 0, 0); MODULE_DEPEND(dpt, pci, 1, 1, 1); MODULE_DEPEND(dpt, cam, 1, 1, 1); diff --git a/sys/dev/iir/iir_pci.c b/sys/dev/iir/iir_pci.c index 662f06bc3b2f..7baee86711b0 100644 --- a/sys/dev/iir/iir_pci.c +++ b/sys/dev/iir/iir_pci.c @@ -1,484 +1,483 @@ /*- * Copyright (c) 2000-03 ICP vortex GmbH * Copyright (c) 2002-03 Intel Corporation * Copyright (c) 2003 Adaptec Inc. * All Rights Reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * iir_pci.c: PCI Bus Attachment for Intel Integrated RAID Controller driver * * Written by: Achim Leubner * Written by: Achim Leubner * Fixes/Additions: Boji Tony Kannanthanam * * TODO: */ /* #include "opt_iir.h" */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Mapping registers for various areas */ #define PCI_DPMEM PCIR_BAR(0) /* Product numbers for Fibre-Channel are greater than or equal to 0x200 */ #define GDT_PCI_PRODUCT_FC 0x200 /* PCI SRAM structure */ #define GDT_MAGIC 0x00 /* u_int32_t, controller ID from BIOS */ #define GDT_NEED_DEINIT 0x04 /* u_int16_t, switch between BIOS/driver */ #define GDT_SWITCH_SUPPORT 0x06 /* u_int8_t, see GDT_NEED_DEINIT */ #define GDT_OS_USED 0x10 /* u_int8_t [16], OS code per service */ #define GDT_FW_MAGIC 0x3c /* u_int8_t, controller ID from firmware */ #define GDT_SRAM_SZ 0x40 /* DPRAM PCI controllers */ #define GDT_DPR_IF 0x00 /* interface area */ #define GDT_6SR (0xff0 - GDT_SRAM_SZ) #define GDT_SEMA1 0xff1 /* volatile u_int8_t, command semaphore */ #define GDT_IRQEN 0xff5 /* u_int8_t, board interrupts enable */ #define GDT_EVENT 0xff8 /* u_int8_t, release event */ #define GDT_IRQDEL 0xffc /* u_int8_t, acknowledge board interrupt */ #define GDT_DPRAM_SZ 0x1000 /* PLX register structure (new PCI controllers) */ #define GDT_CFG_REG 0x00 /* u_int8_t, DPRAM cfg. (2: < 1MB, 0: any) */ #define GDT_SEMA0_REG 0x40 /* volatile u_int8_t, command semaphore */ #define GDT_SEMA1_REG 0x41 /* volatile u_int8_t, status semaphore */ #define GDT_PLX_STATUS 0x44 /* volatile u_int16_t, command status */ #define GDT_PLX_SERVICE 0x46 /* u_int16_t, service */ #define GDT_PLX_INFO 0x48 /* u_int32_t [2], additional info */ #define GDT_LDOOR_REG 0x60 /* u_int8_t, PCI to local doorbell */ #define GDT_EDOOR_REG 0x64 /* volatile u_int8_t, local to PCI doorbell */ #define GDT_CONTROL0 0x68 /* u_int8_t, control0 register (unused) */ #define GDT_CONTROL1 0x69 /* u_int8_t, board interrupts enable */ #define GDT_PLX_SZ 0x80 /* DPRAM new PCI controllers */ #define GDT_IC 0x00 /* interface */ #define GDT_PCINEW_6SR (0x4000 - GDT_SRAM_SZ) /* SRAM structure */ #define GDT_PCINEW_SZ 0x4000 /* i960 register structure (PCI MPR controllers) */ #define GDT_MPR_SEMA0 0x10 /* volatile u_int8_t, command semaphore */ #define GDT_MPR_SEMA1 0x12 /* volatile u_int8_t, status semaphore */ #define GDT_MPR_STATUS 0x14 /* volatile u_int16_t, command status */ #define GDT_MPR_SERVICE 0x16 /* u_int16_t, service */ #define GDT_MPR_INFO 0x18 /* u_int32_t [2], additional info */ #define GDT_MPR_LDOOR 0x20 /* u_int8_t, PCI to local doorbell */ #define GDT_MPR_EDOOR 0x2c /* volatile u_int8_t, locl to PCI doorbell */ #define GDT_EDOOR_EN 0x34 /* u_int8_t, board interrupts enable */ #define GDT_SEVERITY 0xefc /* u_int8_t, event severity */ #define GDT_EVT_BUF 0xf00 /* u_int8_t [256], event buffer */ #define GDT_I960_SZ 0x1000 /* DPRAM PCI MPR controllers */ #define GDT_I960R 0x00 /* 4KB i960 registers */ #define GDT_MPR_IC GDT_I960_SZ /* i960 register area */ #define GDT_MPR_6SR (GDT_I960_SZ + 0x3000 - GDT_SRAM_SZ) /* DPRAM struct. */ #define GDT_MPR_SZ (0x3000 - GDT_SRAM_SZ) static int iir_pci_probe(device_t dev); static int iir_pci_attach(device_t dev); void gdt_pci_enable_intr(struct gdt_softc *); void gdt_mpr_copy_cmd(struct gdt_softc *, struct gdt_ccb *); u_int8_t gdt_mpr_get_status(struct gdt_softc *); void gdt_mpr_intr(struct gdt_softc *, struct gdt_intr_ctx *); void gdt_mpr_release_event(struct gdt_softc *); void gdt_mpr_set_sema0(struct gdt_softc *); int gdt_mpr_test_busy(struct gdt_softc *); static device_method_t iir_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, iir_pci_probe), DEVMETHOD(device_attach, iir_pci_attach), { 0, 0} }; static driver_t iir_pci_driver = { "iir", iir_pci_methods, sizeof(struct gdt_softc) }; static devclass_t iir_devclass; DRIVER_MODULE(iir, pci, iir_pci_driver, iir_devclass, 0, 0); MODULE_DEPEND(iir, pci, 1, 1, 1); MODULE_DEPEND(iir, cam, 1, 1, 1); static int iir_pci_probe(device_t dev) { if (pci_get_vendor(dev) == INTEL_VENDOR_ID && pci_get_device(dev) == INTEL_DEVICE_ID_IIR) { device_set_desc(dev, "Intel Integrated RAID Controller"); return (BUS_PROBE_DEFAULT); } if (pci_get_vendor(dev) == GDT_VENDOR_ID && ((pci_get_device(dev) >= GDT_DEVICE_ID_MIN && pci_get_device(dev) <= GDT_DEVICE_ID_MAX) || pci_get_device(dev) == GDT_DEVICE_ID_NEWRX)) { device_set_desc(dev, "ICP Disk Array Controller"); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int iir_pci_attach(device_t dev) { struct gdt_softc *gdt; struct resource *io = NULL, *irq = NULL; int retries, rid, error = 0; void *ih; u_int8_t protocol; /* map DPMEM */ rid = PCI_DPMEM; io = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (io == NULL) { device_printf(dev, "can't allocate register resources\n"); error = ENOMEM; goto err; } /* get IRQ */ rid = 0; irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE | RF_SHAREABLE); if (irq == NULL) { device_printf(dev, "can't find IRQ value\n"); error = ENOMEM; goto err; } gdt = device_get_softc(dev); gdt->sc_devnode = dev; gdt->sc_init_level = 0; gdt->sc_dpmemt = rman_get_bustag(io); gdt->sc_dpmemh = rman_get_bushandle(io); gdt->sc_dpmembase = rman_get_start(io); gdt->sc_hanum = device_get_unit(dev); gdt->sc_bus = pci_get_bus(dev); gdt->sc_slot = pci_get_slot(dev); gdt->sc_vendor = pci_get_vendor(dev); gdt->sc_device = pci_get_device(dev); gdt->sc_subdevice = pci_get_subdevice(dev); gdt->sc_class = GDT_MPR; /* no FC ctr. if (gdt->sc_device >= GDT_PCI_PRODUCT_FC) gdt->sc_class |= GDT_FC; */ /* initialize RP controller */ /* check and reset interface area */ bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC, htole32(GDT_MPR_MAGIC)); if (bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC) != htole32(GDT_MPR_MAGIC)) { printf("cannot access DPMEM at 0x%jx (shadowed?)\n", (uintmax_t)gdt->sc_dpmembase); error = ENXIO; goto err; } bus_space_set_region_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_I960_SZ, htole32(0), GDT_MPR_SZ >> 2); /* Disable everything */ bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_EDOOR_EN, bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_EDOOR_EN) | 4); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR, 0xff); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS, 0); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_CMD_INDEX, 0); bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO, htole32(gdt->sc_dpmembase)); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_CMD_INDX, 0xff); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_LDOOR, 1); DELAY(20); retries = GDT_RETRIES; while (bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS) != 0xff) { if (--retries == 0) { printf("DEINIT failed\n"); error = ENXIO; goto err; } DELAY(1); } protocol = (uint8_t)le32toh(bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO)); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS, 0); if (protocol != GDT_PROTOCOL_VERSION) { printf("unsupported protocol %d\n", protocol); error = ENXIO; goto err; } /* special commnd to controller BIOS */ bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO, htole32(0)); bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO + sizeof (u_int32_t), htole32(0)); bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO + 2 * sizeof (u_int32_t), htole32(1)); bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO + 3 * sizeof (u_int32_t), htole32(0)); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_CMD_INDX, 0xfe); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_LDOOR, 1); DELAY(20); retries = GDT_RETRIES; while (bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS) != 0xfe) { if (--retries == 0) { printf("initialization error\n"); error = ENXIO; goto err; } DELAY(1); } bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS, 0); gdt->sc_ic_all_size = GDT_MPR_SZ; gdt->sc_copy_cmd = gdt_mpr_copy_cmd; gdt->sc_get_status = gdt_mpr_get_status; gdt->sc_intr = gdt_mpr_intr; gdt->sc_release_event = gdt_mpr_release_event; gdt->sc_set_sema0 = gdt_mpr_set_sema0; gdt->sc_test_busy = gdt_mpr_test_busy; /* Allocate a dmatag representing the capabilities of this attachment */ - /* XXX Should be a child of the PCI bus dma tag */ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignemnt*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, /*nsegments*/GDT_MAXSG, /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, /*flags*/0, /*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant, &gdt->sc_parent_dmat) != 0) { error = ENXIO; goto err; } gdt->sc_init_level++; if (iir_init(gdt) != 0) { iir_free(gdt); error = ENXIO; goto err; } /* Register with the XPT */ iir_attach(gdt); /* associate interrupt handler */ if (bus_setup_intr( dev, irq, INTR_TYPE_CAM, NULL, iir_intr, gdt, &ih )) { device_printf(dev, "Unable to register interrupt handler\n"); error = ENXIO; goto err; } gdt_pci_enable_intr(gdt); return (0); err: if (irq) bus_release_resource( dev, SYS_RES_IRQ, 0, irq ); /* if (io) bus_release_resource( dev, SYS_RES_MEMORY, rid, io ); */ return (error); } /* Enable interrupts */ void gdt_pci_enable_intr(struct gdt_softc *gdt) { GDT_DPRINTF(GDT_D_INTR, ("gdt_pci_enable_intr(%p) ", gdt)); switch(GDT_CLASS(gdt)) { case GDT_MPR: bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR, 0xff); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_EDOOR_EN, bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_EDOOR_EN) & ~4); break; } } /* * MPR PCI controller-specific functions */ void gdt_mpr_copy_cmd(struct gdt_softc *gdt, struct gdt_ccb *gccb) { u_int16_t cp_count = roundup(gccb->gc_cmd_len, sizeof (u_int32_t)); u_int16_t dp_offset = gdt->sc_cmd_off; u_int16_t cmd_no = gdt->sc_cmd_cnt++; GDT_DPRINTF(GDT_D_CMD, ("gdt_mpr_copy_cmd(%p) ", gdt)); gdt->sc_cmd_off += cp_count; bus_space_write_region_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_DPR_CMD + dp_offset, (u_int32_t *)gccb->gc_cmd, cp_count >> 2); bus_space_write_2(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_COMM_QUEUE + cmd_no * GDT_COMM_Q_SZ + GDT_OFFSET, htole16(GDT_DPMEM_COMMAND_OFFSET + dp_offset)); bus_space_write_2(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_COMM_QUEUE + cmd_no * GDT_COMM_Q_SZ + GDT_SERV_ID, htole16(gccb->gc_service)); } u_int8_t gdt_mpr_get_status(struct gdt_softc *gdt) { GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_get_status(%p) ", gdt)); return bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR); } void gdt_mpr_intr(struct gdt_softc *gdt, struct gdt_intr_ctx *ctx) { int i; GDT_DPRINTF(GDT_D_INTR, ("gdt_mpr_intr(%p) ", gdt)); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR, 0xff); if (ctx->istatus & 0x80) { /* error flag */ ctx->istatus &= ~0x80; ctx->cmd_status = bus_space_read_2(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_STATUS); } else /* no error */ ctx->cmd_status = GDT_S_OK; ctx->info = bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_INFO); ctx->service = bus_space_read_2(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_SERVICE); ctx->info2 = bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_INFO + sizeof (u_int32_t)); /* event string */ if (ctx->istatus == GDT_ASYNCINDEX) { if (ctx->service != GDT_SCREENSERVICE && (gdt->sc_fw_vers & 0xff) >= 0x1a) { gdt->sc_dvr.severity = bus_space_read_1(gdt->sc_dpmemt,gdt->sc_dpmemh, GDT_SEVERITY); for (i = 0; i < 256; ++i) { gdt->sc_dvr.event_string[i] = bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_EVT_BUF + i); if (gdt->sc_dvr.event_string[i] == 0) break; } } } bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_SEMA1, 0); } void gdt_mpr_release_event(struct gdt_softc *gdt) { GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_release_event(%p) ", gdt)); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_LDOOR, 1); } void gdt_mpr_set_sema0(struct gdt_softc *gdt) { GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_set_sema0(%p) ", gdt)); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_SEMA0, 1); } int gdt_mpr_test_busy(struct gdt_softc *gdt) { GDT_DPRINTF(GDT_D_MISC, ("gdt_mpr_test_busy(%p) ", gdt)); return (bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_SEMA0) & 1); }