aha_isa.c revision 157085
180709Sjake/* 280709Sjake * Product specific probe and attach routines for: 380709Sjake * Adaptec 154x. 480709Sjake */ 580709Sjake/*- 680709Sjake * Copyright (c) 1999-2003 M. Warner Losh 780709Sjake * All rights reserved. 880709Sjake * 980709Sjake * Redistribution and use in source and binary forms, with or without 1080709Sjake * modification, are permitted provided that the following conditions 1180709Sjake * are met: 1280709Sjake * 1. Redistributions of source code must retain the above copyright 1380709Sjake * notice, this list of conditions, and the following disclaimer, 1481337Sobrien * without modification, immediately at the beginning of the file. 1580709Sjake * 2. The name of the author may not be used to endorse or promote products 1680709Sjake * derived from this software without specific prior written permission. 1781337Sobrien * 1880709Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1980709Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2080709Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2180709Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2280709Sjake * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2380709Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2480709Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2580709Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2680709Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27114188Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28114188Sjake * SUCH DAMAGE. 29114188Sjake * 30166105Smarius * Derived from bt isa from end, written by: 31166105Smarius * 3280709Sjake * Copyright (c) 1998 Justin T. Gibbs 3380709Sjake * All rights reserved. 34166105Smarius * 35166105Smarius * Redistribution and use in source and binary forms, with or without 36166105Smarius * modification, are permitted provided that the following conditions 3782909Sjake * are met: 38205409Smarius * 1. Redistributions of source code must retain the above copyright 3980709Sjake * notice, this list of conditions, and the following disclaimer, 4080709Sjake * without modification, immediately at the beginning of the file. 4180709Sjake * 2. The name of the author may not be used to endorse or promote products 4288641Sjake * derived from this software without specific prior written permission. 4388641Sjake * 4488641Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 4588641Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4684193Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4784193Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 4884193Sjake * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4984193Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5084193Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5184193Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5284193Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5384193Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5484193Sjake * SUCH DAMAGE. 5584193Sjake */ 5684193Sjake 5784193Sjake#include <sys/cdefs.h> 5884193Sjake__FBSDID("$FreeBSD: head/sys/dev/aha/aha_isa.c 157085 2006-03-24 06:33:25Z imp $"); 5984193Sjake 6084193Sjake#include <sys/param.h> 6184193Sjake#include <sys/systm.h> 6284193Sjake#include <sys/kernel.h> 6384193Sjake#include <sys/lock.h> 6484193Sjake#include <sys/mutex.h> 6584193Sjake 6684193Sjake#include <machine/bus.h> 6784193Sjake#include <machine/resource.h> 6884193Sjake#include <sys/module.h> 6984193Sjake#include <sys/bus.h> 7084193Sjake#include <sys/rman.h> 7184193Sjake 7284193Sjake#include <isa/isavar.h> 7384193Sjake 74116589Sjake#include <dev/aha/ahareg.h> 7580709Sjake 7684193Sjake#include <cam/scsi/scsi_all.h> 7784193Sjake 7884193Sjakestatic struct isa_pnp_id aha_ids[] = { 7984193Sjake {ADP0100_PNP, "Adaptec 1540/1542 ISA SCSI"}, /* ADP0100 */ 8084193Sjake {AHA1540_PNP, "Adaptec 1540/aha-1640/aha-1535"},/* ADP1540 */ 8180709Sjake {AHA1542_PNP, "Adaptec 1542/aha-1535"}, /* ADP1542 */ 8284193Sjake {AHA1542_PNPCOMPAT, "Adaptec 1542 compatible"}, /* PNP00A0 */ 8384193Sjake {ICU0091_PNP, "Adaptec AHA-1540/1542 SCSI"}, /* ICU0091 */ 8486520Sjake {0} 8584193Sjake}; 8684193Sjake 8784193Sjake/* 8884193Sjake * I/O ports listed in the order enumerated by the card for certain op codes. 8984193Sjake */ 9084193Sjakestatic bus_addr_t aha_board_ports[] = 9184193Sjake{ 9284193Sjake 0x330, 9384193Sjake 0x334, 9484193Sjake 0x230, 9584193Sjake 0x234, 9684193Sjake 0x130, 9784193Sjake 0x134 9884193Sjake}; 9984193Sjake 10084193Sjake/* 10184193Sjake * Check if the device can be found at the port given 10284193Sjake */ 10384193Sjakestatic int 10484193Sjakeaha_isa_probe(device_t dev) 105114189Sjake{ 10684193Sjake /* 10784193Sjake * find unit and check we have that many defined 10884193Sjake */ 10984193Sjake struct aha_softc *aha = device_get_softc(dev); 11084193Sjake int error; 11184193Sjake u_long port_start; 112116589Sjake struct resource *port_res; 11384193Sjake int port_rid; 114114189Sjake int drq; 11584193Sjake int irq; 11684193Sjake config_data_t config_data; 11784193Sjake 11884193Sjake aha->dev = dev; 11984193Sjake /* Check isapnp ids */ 12084193Sjake if (ISA_PNP_PROBE(device_get_parent(dev), dev, aha_ids) == ENXIO) 12184193Sjake return (ENXIO); 122116589Sjake 12384193Sjake port_rid = 0; 124114189Sjake port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &port_rid, 12584193Sjake 0, ~0, AHA_NREGS, RF_ACTIVE); 12684193Sjake 12784193Sjake if (port_res == NULL) 12884193Sjake return (ENXIO); 129116589Sjake 13084193Sjake port_start = rman_get_start(port_res); 131114189Sjake aha_alloc(aha, device_get_unit(dev), rman_get_bustag(port_res), 13284193Sjake rman_get_bushandle(port_res)); 13384193Sjake 13484193Sjake /* See if there is really a card present */ 13584193Sjake if (aha_probe(aha) || aha_fetch_adapter_info(aha)) { 136116589Sjake aha_free(aha); 13784193Sjake bus_release_resource(dev, SYS_RES_IOPORT, port_rid, port_res); 13884193Sjake return (ENXIO); 13980709Sjake } 14084193Sjake 14184193Sjake /* 14286520Sjake * Determine our IRQ, and DMA settings and 14386520Sjake * export them to the configuration system. 14484193Sjake */ 14584193Sjake error = aha_cmd(aha, AOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 14684193Sjake (uint8_t*)&config_data, sizeof(config_data), DEFAULT_CMD_TIMEOUT); 14784193Sjake 14884193Sjake if (error != 0) { 14988641Sjake device_printf(dev, "Could not determine IRQ or DMA " 15084193Sjake "settings for adapter at %#jx. Failing probe\n", 15184193Sjake (uintmax_t)port_start); 15284193Sjake aha_free(aha); 15384193Sjake bus_release_resource(dev, SYS_RES_IOPORT, port_rid, 15484193Sjake port_res); 15584193Sjake return (ENXIO); 15684193Sjake } 15784193Sjake 15884193Sjake bus_release_resource(dev, SYS_RES_IOPORT, port_rid, port_res); 15984193Sjake 16084193Sjake switch (config_data.dma_chan) { 16184193Sjake case DMA_CHAN_5: 16284193Sjake drq = 5; 16380709Sjake break; 16484193Sjake case DMA_CHAN_6: 165116589Sjake drq = 6; 16684193Sjake break; 167114189Sjake case DMA_CHAN_7: 16884193Sjake drq = 7; 16984193Sjake break; 17084193Sjake default: 171116589Sjake device_printf(dev, "Invalid DMA setting for adapter at %#jx.", 172114189Sjake (uintmax_t)port_start); 17384193Sjake return (ENXIO); 17484193Sjake } 17584193Sjake error = bus_set_resource(dev, SYS_RES_DRQ, 0, drq, 1); 17684193Sjake if (error) 17784193Sjake return error; 17884193Sjake 17984193Sjake irq = ffs(config_data.irq) + 8; 18084193Sjake error = bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1); 18184193Sjake return (error); 18284193Sjake} 18384193Sjake 18484193Sjake/* 185116589Sjake * Attach all the sub-devices we can find 18684193Sjake */ 187114189Sjakestatic int 18884193Sjakeaha_isa_attach(device_t dev) 18984193Sjake{ 19084193Sjake struct aha_softc *aha = device_get_softc(dev); 19184193Sjake bus_dma_filter_t *filter; 19284193Sjake void *filter_arg; 19384193Sjake bus_addr_t lowaddr; 194116589Sjake void *ih; 19584193Sjake int error = ENOMEM; 196114189Sjake int aha_free_needed = 0; 19784193Sjake 19884193Sjake aha->dev = dev; 19984193Sjake aha->portrid = 0; 20084193Sjake aha->port = bus_alloc_resource(dev, SYS_RES_IOPORT, &aha->portrid, 20184193Sjake 0, ~0, AHA_NREGS, RF_ACTIVE); 20280709Sjake if (!aha->port) { 203116589Sjake device_printf(dev, "Unable to allocate I/O ports\n"); 20480709Sjake goto fail; 20584193Sjake } 20680709Sjake 207101955Sjake aha->irqrid = 0; 208101955Sjake aha->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &aha->irqrid, 209101955Sjake RF_ACTIVE); 210101955Sjake if (!aha->irq) { 211101955Sjake device_printf(dev, "Unable to allocate excluse use of irq\n"); 212101955Sjake goto fail; 213101955Sjake } 214101955Sjake 215101955Sjake aha->drqrid = 0; 21680709Sjake aha->drq = bus_alloc_resource_any(dev, SYS_RES_DRQ, &aha->drqrid, 217101955Sjake RF_ACTIVE); 218101955Sjake if (!aha->drq) { 219101955Sjake device_printf(dev, "Unable to allocate drq\n"); 220101955Sjake goto fail; 221101955Sjake } 222216802Smarius 223101955Sjake#if 0 /* is the drq ever unset? */ 224101955Sjake if (dev->id_drq != -1) 225101955Sjake isa_dmacascade(dev->id_drq); 22680709Sjake#endif 227101955Sjake isa_dmacascade(rman_get_start(aha->drq)); 228101955Sjake 229101955Sjake /* Allocate our parent dmatag */ 230101955Sjake filter = NULL; 231101955Sjake filter_arg = NULL; 232216802Smarius lowaddr = BUS_SPACE_MAXADDR_24BIT; 233101955Sjake 234101955Sjake if (bus_dma_tag_create( /* parent */ NULL, 235101955Sjake /* alignemnt */ 1, 23680709Sjake /* boundary */ 0, 237101955Sjake /* lowaddr */ lowaddr, 238101955Sjake /* highaddr */ BUS_SPACE_MAXADDR, 239101955Sjake /* filter */ filter, 240101955Sjake /* filterarg */ filter_arg, 241101955Sjake /* maxsize */ BUS_SPACE_MAXSIZE_24BIT, 242101955Sjake /* nsegments */ ~0, 243101955Sjake /* maxsegsz */ BUS_SPACE_MAXSIZE_24BIT, 244101955Sjake /* flags */ 0, 245101955Sjake /* lockfunc */ busdma_lock_mutex, 24680709Sjake /* lockarg */ &Giant, 24780709Sjake &aha->parent_dmat) != 0) { 24884193Sjake device_printf(dev, "dma tag create failed.\n"); 24980709Sjake goto fail; 25080709Sjake } 25180709Sjake 25280709Sjake if (aha_init(aha)) { 25380709Sjake device_printf(dev, "init failed\n"); 25480709Sjake goto fail; 25580709Sjake } 25684193Sjake /* 25780709Sjake * The 1542A and B look the same. So we guess based on 25880709Sjake * the firmware revision. It appears that only rev 0 is on 25980709Sjake * the A cards. 26080709Sjake */ 26180709Sjake if (aha->boardid <= BOARD_1542 && aha->fw_major == 0) { 26280709Sjake device_printf(dev, "154xA may not work\n"); 26380709Sjake aha->ccb_sg_opcode = INITIATOR_SG_CCB; 26480709Sjake aha->ccb_ccb_opcode = INITIATOR_CCB; 26580709Sjake } 26680709Sjake aha_free_needed++; 26780709Sjake 26886520Sjake error = aha_attach(aha); 26984193Sjake if (error) { 27084193Sjake device_printf(dev, "attach failed\n"); 27184193Sjake goto fail; 27284193Sjake } 27384193Sjake 27484193Sjake error = bus_setup_intr(dev, aha->irq, INTR_TYPE_CAM|INTR_ENTROPY, 27584193Sjake aha_intr, aha, &ih); 27684193Sjake if (error) { 27784193Sjake device_printf(dev, "Unable to register interrupt handler\n"); 27884193Sjake goto fail; 27984193Sjake } 28084193Sjake 28184193Sjake return (0); 28284193Sjakefail: ; 28384193Sjake bus_free_resource(dev, SYS_RES_IOPORT, aha->port); 28484193Sjake bus_free_resource(dev, SYS_RES_IRQ, aha->irq); 28584193Sjake bus_free_resource(dev, SYS_RES_DRQ, aha->drq); 28684193Sjake if (aha_free_needed) 28784193Sjake aha_free(aha); 288116589Sjake return (error); 28984193Sjake} 29084193Sjake 29184193Sjakestatic int 29284193Sjakeaha_isa_detach(device_t dev) 29384193Sjake{ 29484193Sjake struct aha_softc *aha = (struct aha_softc *)device_get_softc(dev); 29584193Sjake int error; 296216802Smarius 29780709Sjake error = bus_teardown_intr(dev, aha->irq, aha->ih); 29880709Sjake if (error) 29980709Sjake device_printf(dev, "failed to unregister interrupt handler\n"); 30080709Sjake 30180709Sjake bus_free_resource(dev, SYS_RES_IOPORT, aha->port); 30284193Sjake bus_free_resource(dev, SYS_RES_IRQ, aha->irq); 30380709Sjake bus_free_resource(dev, SYS_RES_DRQ, aha->drq); 30484193Sjake 305216802Smarius error = aha_detach(aha); 30680709Sjake if (error) { 30780709Sjake device_printf(dev, "detach failed\n"); 30884193Sjake return (error); 30980709Sjake } 31080709Sjake aha_free(aha); 311101955Sjake 31280709Sjake return (0); 313101955Sjake} 314216802Smarius 31584193Sjakestatic void 316101955Sjakeaha_isa_identify(driver_t *driver, device_t parent) 317101955Sjake{ 31884193Sjake int i; 31984193Sjake bus_addr_t ioport; 32080709Sjake struct aha_softc aha; 32180709Sjake int rid; 32280709Sjake struct resource *res; 32384193Sjake device_t child; 324216802Smarius 32580709Sjake /* Attempt to find an adapter */ 32680709Sjake for (i = 0; i < sizeof(aha_board_ports) / sizeof(aha_board_ports[0]); 32780709Sjake i++) { 32880709Sjake bzero(&aha, sizeof(aha)); 32980709Sjake ioport = aha_board_ports[i]; 33084193Sjake /* 33184193Sjake * XXX Check to see if we have a hard-wired aha device at 33284193Sjake * XXX this port, if so, skip. This should also cover the 33384193Sjake * XXX case where we are run multiple times due to, eg, 334216802Smarius * XXX kldload/kldunload. 33584193Sjake */ 33684193Sjake rid = 0; 33784193Sjake res = bus_alloc_resource(parent, SYS_RES_IOPORT, &rid, 33884193Sjake ioport, ioport, AHA_NREGS, RF_ACTIVE); 339101955Sjake if (res == NULL) 340101955Sjake continue; 341101955Sjake aha_alloc(&aha, -1, rman_get_bustag(res), 342101955Sjake rman_get_bushandle(res)); 34384193Sjake /* See if there is really a card present */ 34480709Sjake if (aha_probe(&aha) || aha_fetch_adapter_info(&aha)) 34580709Sjake goto not_this_one; 34680709Sjake child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "aha", -1); 34784193Sjake bus_set_resource(child, SYS_RES_IOPORT, 0, ioport, AHA_NREGS); 348216802Smarius /* 34980709Sjake * Could query the board and set IRQ/DRQ, but probe does 35080709Sjake * that. 35180709Sjake */ 35280709Sjake not_this_one:; 35380709Sjake bus_release_resource(parent, SYS_RES_IOPORT, rid, res); 35480709Sjake aha_free(&aha); 35580709Sjake } 35680709Sjake} 35784193Sjake 358216802Smariusstatic device_method_t aha_isa_methods[] = { 35980709Sjake /* Device interface */ 36084193Sjake DEVMETHOD(device_probe, aha_isa_probe), 36180709Sjake DEVMETHOD(device_attach, aha_isa_attach), 36280709Sjake DEVMETHOD(device_detach, aha_isa_detach), 36380709Sjake DEVMETHOD(device_identify, aha_isa_identify), 36480709Sjake 36580709Sjake { 0, 0 } 36680709Sjake}; 36784193Sjake 368216802Smariusstatic driver_t aha_isa_driver = { 36980709Sjake "aha", 37080709Sjake aha_isa_methods, 37180709Sjake sizeof(struct aha_softc), 37280709Sjake}; 373101955Sjake 374101955Sjakestatic devclass_t aha_devclass; 375101955Sjake 376101955SjakeDRIVER_MODULE(aha, isa, aha_isa_driver, aha_devclass, 0, 0); 377101955SjakeMODULE_DEPEND(aha, cam, 1, 1, 1); 37880709Sjake