aha_isa.c revision 39225
1/* 2 * Product specific probe and attach routines for: 3 * Adaptec 154x. 4 * 5 * Derived from code written by: 6 * 7 * Copyright (c) 1998 Justin T. Gibbs 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions, and the following disclaimer, 15 * without modification, immediately at the beginning of the file. 16 * 2. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * $Id$ 32 */ 33 34#include <sys/param.h> 35#include <sys/systm.h> 36 37#include <machine/bus_pio.h> 38#include <machine/bus.h> 39 40#include <i386/isa/isa_device.h> 41#include <dev/aha/ahareg.h> 42 43#include <cam/scsi/scsi_all.h> 44 45#include "ioconf.h" 46 47static int aha_isa_probe __P((struct isa_device *dev)); 48static int aha_isa_attach __P((struct isa_device *dev)); 49static void aha_isa_intr __P((void *unit)); 50 51struct isa_driver ahadriver = 52{ 53 aha_isa_probe, 54 aha_isa_attach, 55 "aha" 56}; 57 58/* 59 * Check if the device can be found at the port given 60 * and if so, set it up ready for further work 61 * as an argument, takes the isa_device structure from 62 * autoconf.c 63 */ 64static int 65aha_isa_probe(dev) 66 struct isa_device *dev; 67{ 68 /* 69 * find unit and check we have that many defined 70 */ 71 struct aha_softc *aha; 72 int port_index; 73 int max_port_index; 74 75 /* 76 * We ignore the unit number assigned by config to allow 77 * consistant numbering between PCI/EISA/ISA devices. 78 * This is a total kludge until we have a configuration 79 * manager. 80 */ 81 dev->id_unit = aha_unit; 82 83 aha = NULL; 84 port_index = 0; 85 max_port_index = AHA_NUM_ISAPORTS - 1; 86 /* 87 * Bound our board search if the user has 88 * specified an exact port. 89 */ 90 if (dev->id_iobase > 0) { 91 for (;port_index <= max_port_index; port_index++) 92 if (dev->id_iobase >= aha_isa_ports[port_index].addr) 93 break; 94 if ((port_index > max_port_index) 95 || (dev->id_iobase != aha_isa_ports[port_index].addr)) { 96 printf(" 97aha_isa_probe: Invalid baseport of 0x%x specified. 98aha_isa_probe: Nearest valid baseport is 0x%x. 99aha_isa_probe: Failing probe.\n", 100 dev->id_iobase, 101 (port_index <= max_port_index) 102 ? aha_isa_ports[port_index].addr 103 : aha_isa_ports[max_port_index].addr); 104 return 0; 105 } 106 } 107 108 /* Attempt to find an adapter */ 109 for (;port_index <= max_port_index; port_index++) { 110 config_data_t config_data; 111 u_int ioport; 112 int error; 113 114 ioport = aha_isa_ports[port_index].addr; 115 116 /* 117 * Ensure this port has not already been claimed already 118 * by a PCI or EISA adapter. 119 */ 120 if (aha_check_probed_iop(ioport) != 0) 121 continue; 122 123 /* Allocate a softc for use during probing */ 124 aha = aha_alloc(dev->id_unit, I386_BUS_SPACE_IO, ioport); 125 126 if (aha == NULL) 127 break; 128 129 /* We're going to attempt to probe it now, so mark it probed */ 130 aha_mark_probed_bio(port_index); 131 132 /* See if there is really a card present */ 133 if (aha_probe(aha) || aha_fetch_adapter_info(aha)) { 134 aha_free(aha); 135 continue; 136 } 137 138 /* 139 * Determine our IRQ, and DMA settings and 140 * export them to the configuration system. 141 */ 142 error = aha_cmd(aha, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 143 (u_int8_t*)&config_data, sizeof(config_data), 144 DEFAULT_CMD_TIMEOUT); 145 if (error != 0) { 146 printf("aha_isa_probe: Could not determine IRQ or DMA " 147 "settings for adapter at 0x%x. Failing probe\n", 148 ioport); 149 aha_free(aha); 150 continue; 151 } 152 153 switch (config_data.dma_chan) { 154 case DMA_CHAN_5: 155 dev->id_drq = 5; 156 break; 157 case DMA_CHAN_6: 158 dev->id_drq = 6; 159 break; 160 case DMA_CHAN_7: 161 dev->id_drq = 7; 162 break; 163 default: 164 printf("aha_isa_probe: Invalid DMA setting " 165 "detected for adapter at 0x%x. " 166 "Failing probe\n", ioport); 167 } 168 dev->id_iobase = aha_isa_ports[port_index].addr; 169 dev->id_irq = (config_data.irq << 9); 170 dev->id_intr = aha_isa_intr; 171 aha_unit++; 172 return (AHA_NREGS); 173 } 174 175 return (0); 176} 177 178/* 179 * Attach all the sub-devices we can find 180 */ 181static int 182aha_isa_attach(dev) 183 struct isa_device *dev; 184{ 185 struct aha_softc *aha; 186 bus_dma_filter_t *filter; 187 void *filter_arg; 188 bus_addr_t lowaddr; 189 190 aha = aha_softcs[dev->id_unit]; 191 if (dev->id_drq != -1) 192 isa_dmacascade(dev->id_drq); 193 194 /* Allocate our parent dmatag */ 195 filter = NULL; 196 filter_arg = NULL; 197 lowaddr = BUS_SPACE_MAXADDR_24BIT; 198 199 if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0, 200 lowaddr, /*highaddr*/BUS_SPACE_MAXADDR, 201 filter, filter_arg, 202 /*maxsize*/BUS_SPACE_MAXSIZE_24BIT, 203 /*nsegments*/BUS_SPACE_UNRESTRICTED, 204 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT, 205 /*flags*/0, &aha->parent_dmat) != 0) { 206 aha_free(aha); 207 return (-1); 208 } 209 210 if (aha_init(aha)) { 211 printf("aha init failed\n"); 212 aha_free(aha); 213 return (-1); 214 } 215 216 return (aha_attach(aha)); 217} 218 219/* 220 * Handle an ISA interrupt. 221 * XXX should go away as soon as ISA interrupt handlers 222 * take a (void *) arg. 223 */ 224static void 225aha_isa_intr(void *unit) 226{ 227 struct aha_softc* arg = aha_softcs[(int)unit]; 228 aha_intr((void *)arg); 229} 230