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