aha_isa.c revision 51713
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 * $FreeBSD: head/sys/dev/aha/aha_isa.c 50782 1999-09-02 04:37:07Z peter $ 32 */ 33 34/* #include "pnp.h" */ 35#define NPNP 0 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/kernel.h> 40 41#include <machine/bus_pio.h> 42#include <machine/bus.h> 43 44#include <i386/isa/isa_device.h> 45#include <dev/aha/ahareg.h> 46 47#include <cam/scsi/scsi_all.h> 48 49#if NPNP > 0 50#include <i386/isa/pnp.h> 51#endif 52 53static int aha_isa_probe(struct isa_device *dev); 54static int aha_isa_attach(struct isa_device *dev); 55static void aha_isa_intr(void *unit); 56 57struct isa_driver ahadriver = 58{ 59 aha_isa_probe, 60 aha_isa_attach, 61 "aha" 62}; 63 64/* 65 * Check if the device can be found at the port given 66 * and if so, set it up ready for further work 67 * as an argument, takes the isa_device structure from 68 * autoconf.c 69 */ 70static int 71aha_isa_probe(dev) 72 struct isa_device *dev; 73{ 74 /* 75 * find unit and check we have that many defined 76 */ 77 struct aha_softc *aha; 78 int port_index; 79 int max_port_index; 80 81 aha = NULL; 82 83 /* 84 * Bound our board search if the user has 85 * specified an exact port. 86 */ 87 aha_find_probe_range(dev->id_iobase, &port_index, &max_port_index); 88 89 if (port_index < 0) 90 return 0; 91 92 /* Attempt to find an adapter */ 93 for (;port_index <= max_port_index; port_index++) { 94 config_data_t config_data; 95 u_int ioport; 96 int error; 97 98 ioport = aha_iop_from_bio(port_index); 99 100 /* 101 * Ensure this port has not already been claimed already 102 * by a PCI, EISA or ISA adapter. 103 */ 104 if (aha_check_probed_iop(ioport) != 0) 105 continue; 106 dev->id_iobase = ioport; 107 if (haveseen_iobase(dev, AHA_NREGS)) 108 continue; 109 110 /* Allocate a softc for use during probing */ 111 aha = aha_alloc(dev->id_unit, I386_BUS_SPACE_IO, ioport); 112 113 if (aha == NULL) 114 break; 115 116 /* We're going to attempt to probe it now, so mark it probed */ 117 aha_mark_probed_bio(port_index); 118 119 /* See if there is really a card present */ 120 if (aha_probe(aha) || aha_fetch_adapter_info(aha)) { 121 aha_free(aha); 122 continue; 123 } 124 125 /* 126 * Determine our IRQ, and DMA settings and 127 * export them to the configuration system. 128 */ 129 error = aha_cmd(aha, AOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 130 (u_int8_t*)&config_data, sizeof(config_data), 131 DEFAULT_CMD_TIMEOUT); 132 if (error != 0) { 133 printf("aha_isa_probe: Could not determine IRQ or DMA " 134 "settings for adapter at 0x%x. Failing probe\n", 135 ioport); 136 aha_free(aha); 137 continue; 138 } 139 140 switch (config_data.dma_chan) { 141 case DMA_CHAN_5: 142 dev->id_drq = 5; 143 break; 144 case DMA_CHAN_6: 145 dev->id_drq = 6; 146 break; 147 case DMA_CHAN_7: 148 dev->id_drq = 7; 149 break; 150 default: 151 printf("aha_isa_probe: Invalid DMA setting " 152 "detected for adapter at 0x%x. " 153 "Failing probe\n", ioport); 154 return (0); 155 } 156 dev->id_irq = (config_data.irq << 9); 157 dev->id_intr = aha_isa_intr; 158 aha_unit++; 159 return (AHA_NREGS); 160 } 161 162 return (0); 163} 164 165/* 166 * Attach all the sub-devices we can find 167 */ 168static int 169aha_isa_attach(dev) 170 struct isa_device *dev; 171{ 172 struct aha_softc *aha; 173 bus_dma_filter_t *filter; 174 void *filter_arg; 175 bus_addr_t lowaddr; 176 177 aha = aha_softcs[dev->id_unit]; 178 if (dev->id_drq != -1) 179 isa_dmacascade(dev->id_drq); 180 181 /* Allocate our parent dmatag */ 182 filter = NULL; 183 filter_arg = NULL; 184 lowaddr = BUS_SPACE_MAXADDR_24BIT; 185 186 if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/1, /*boundary*/0, 187 lowaddr, /*highaddr*/BUS_SPACE_MAXADDR, 188 filter, filter_arg, 189 /*maxsize*/BUS_SPACE_MAXSIZE_24BIT, 190 /*nsegments*/BUS_SPACE_UNRESTRICTED, 191 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT, 192 /*flags*/0, &aha->parent_dmat) != 0) { 193 aha_free(aha); 194 return (-1); 195 } 196 197 if (aha_init(aha)) { 198 printf("aha init failed\n"); 199 aha_free(aha); 200 return (-1); 201 } 202 203 return (aha_attach(aha)); 204} 205 206/* 207 * Handle an ISA interrupt. 208 * XXX should go away as soon as ISA interrupt handlers 209 * take a (void *) arg. 210 */ 211static void 212aha_isa_intr(void *unit) 213{ 214 struct aha_softc* arg = aha_softcs[(int)unit]; 215 aha_intr((void *)arg); 216} 217 218/* 219 * support PnP cards if we are using 'em 220 */ 221 222#if NPNP > 0 223 224static char *ahapnp_probe(u_long csn, u_long vend_id); 225static void ahapnp_attach(u_long csn, u_long vend_id, char *name, 226 struct isa_device *dev); 227static u_long nahapnp = NAHA; 228 229static struct pnp_device ahapnp = { 230 "ahapnp", 231 ahapnp_probe, 232 ahapnp_attach, 233 &nahapnp, 234 &bio_imask 235}; 236DATA_SET (pnpdevice_set, ahapnp); 237 238static char * 239ahapnp_probe(u_long csn, u_long vend_id) 240{ 241 struct pnp_cinfo d; 242 char *s = NULL; 243 244 if (vend_id != AHA1542_PNP && vend_id != AHA1542_PNPCOMPAT) 245 return (NULL); 246 247 read_pnp_parms(&d, 0); 248 if (d.enable == 0 || d.flags & 1) { 249 printf("CSN %lu is disabled.\n", csn); 250 return (NULL); 251 } 252 s = "Adaptec 1542CP"; 253 254 return (s); 255} 256 257static void 258ahapnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) 259{ 260 struct pnp_cinfo d; 261 262 if (dev->id_unit >= NAHATOT) 263 return; 264 265 if (read_pnp_parms(&d, 0) == 0) { 266 printf("failed to read pnp parms\n"); 267 return; 268 } 269 270 write_pnp_parms(&d, 0); 271 272 enable_pnp_card(); 273 274 dev->id_iobase = d.port[0]; 275 dev->id_irq = (1 << d.irq[0]); 276 dev->id_intr = aha_intr; 277 dev->id_drq = d.drq[0]; 278 279 if (dev->id_driver == NULL) { 280 dev->id_driver = &ahadriver; 281 dev->id_id = isa_compat_nextid(); 282 } 283 284 if ((dev->id_alive = aha_isa_probe(dev)) != 0) 285 aha_isa_attach(dev); 286 else 287 printf("aha%d: probe failed\n", dev->id_unit); 288} 289#endif 290