1/* 2 * Product specific probe and attach routines for: 3 * Buslogic BT-54X and BT-445 cards 4 * 5 * Copyright (c) 1998 Justin T. Gibbs 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions, and the following disclaimer, 13 * without modification, immediately at the beginning of the file. 14 * 2. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 *
|
29 * $Id: bt_isa.c,v 1.1 1998/09/15 07:32:54 gibbs Exp $
|
29 * $Id: bt_isa.c,v 1.2 1998/09/24 10:43:42 bde Exp $ |
30 */ 31 32#include <sys/param.h> 33#include <sys/systm.h> 34 35#include <machine/bus_pio.h> 36#include <machine/bus.h> 37 38#include <i386/isa/isa_device.h> 39#include <dev/buslogic/btreg.h> 40 41#include <cam/scsi/scsi_all.h> 42 43static int bt_isa_probe __P((struct isa_device *dev)); 44static int bt_isa_attach __P((struct isa_device *dev)); 45static void bt_isa_intr __P((void *unit)); 46 47static bus_dma_filter_t btvlbouncefilter; 48static bus_dmamap_callback_t btmapsensebuffers; 49 50struct isa_driver btdriver = 51{ 52 bt_isa_probe, 53 bt_isa_attach, 54 "bt" 55}; 56 57/* 58 * Check if the device can be found at the port given 59 * and if so, set it up ready for further work 60 * as an argument, takes the isa_device structure from 61 * autoconf.c 62 */ 63static int 64bt_isa_probe(dev) 65 struct isa_device *dev; 66{ 67 /* 68 * find unit and check we have that many defined 69 */ 70 struct bt_softc *bt; 71 int port_index; 72 int max_port_index; 73 74 /* 75 * We ignore the unit number assigned by config to allow 76 * consistant numbering between PCI/EISA/ISA devices. 77 * This is a total kludge until we have a configuration 78 * manager. 79 */ 80 dev->id_unit = bt_unit; 81 82 bt = NULL; 83 port_index = 0; 84 max_port_index = BT_NUM_ISAPORTS - 1; 85 /* 86 * Bound our board search if the user has 87 * specified an exact port. 88 */ 89 if (dev->id_iobase > 0) { 90 for (;port_index <= max_port_index; port_index++) 91 if (dev->id_iobase >= bt_isa_ports[port_index].addr) 92 break; 93 if ((port_index > max_port_index) 94 || (dev->id_iobase != bt_isa_ports[port_index].addr)) { 95 printf(" 96bt_isa_probe: Invalid baseport of 0x%x specified. 97bt_isa_probe: Nearest valid baseport is 0x%x. 98bt_isa_probe: Failing probe.\n", 99 dev->id_iobase, 100 (port_index <= max_port_index) 101 ? bt_isa_ports[port_index].addr 102 : bt_isa_ports[max_port_index].addr); 103 return 0; 104 }
|
105 max_port_index = port_index; |
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 = bt_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 (bt_check_probed_iop(ioport) != 0) 121 continue; 122
|
123 /* 124 * Make sure that we do not conflict with another device's 125 * I/O address. 126 */ 127 if (haveseen_isadev(dev, CC_IOADDR)) 128 continue; 129 |
130 /* Allocate a softc for use during probing */ 131 bt = bt_alloc(dev->id_unit, I386_BUS_SPACE_IO, ioport); 132 133 if (bt == NULL) 134 break; 135 136 /* We're going to attempt to probe it now, so mark it probed */ 137 bt_mark_probed_bio(port_index); 138 139 /* See if there is really a card present */ 140 if (bt_probe(bt) || bt_fetch_adapter_info(bt)) { 141 bt_free(bt); 142 continue; 143 } 144 145 /* 146 * Determine our IRQ, and DMA settings and 147 * export them to the configuration system. 148 */ 149 error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 150 (u_int8_t*)&config_data, sizeof(config_data), 151 DEFAULT_CMD_TIMEOUT); 152 if (error != 0) { 153 printf("bt_isa_probe: Could not determine IRQ or DMA " 154 "settings for adapter at 0x%x. Failing probe\n", 155 ioport); 156 bt_free(bt); 157 continue; 158 } 159 160 if (bt->model[0] == '5') { 161 /* DMA settings only make sense for ISA cards */ 162 switch (config_data.dma_chan) { 163 case DMA_CHAN_5: 164 dev->id_drq = 5; 165 break; 166 case DMA_CHAN_6: 167 dev->id_drq = 6; 168 break; 169 case DMA_CHAN_7: 170 dev->id_drq = 7; 171 break; 172 default: 173 printf("bt_isa_probe: Invalid DMA setting " 174 "detected for adapter at 0x%x. " 175 "Failing probe\n", ioport); 176 } 177 } else { 178 /* VL DMA */ 179 dev->id_drq = -1; 180 } 181 dev->id_iobase = bt_isa_ports[port_index].addr; 182 dev->id_irq = (config_data.irq << 9); 183 dev->id_intr = bt_isa_intr;
|
184 185 /* 186 * OK, check to make sure that we're not stepping on 187 * someone else's IRQ or DRQ 188 */ 189 if (haveseen_isadev(dev, CC_DRQ)) { 190 printf("bt_isa_probe: Bt card at I/O 0x%x's drq %d " 191 "conflicts, ignoring card.\n", dev->id_iobase, 192 dev->id_drq); 193 bt_free(bt); 194 return 0; 195 } 196 if (haveseen_isadev(dev, CC_IRQ)) { 197 printf("bt_isa_probe: Bt card at I/O 0x%x's irq %d " 198 "conflicts, ignoring card.\n", dev->id_iobase, 199 config_data.irq + 9); 200 bt_free(bt); 201 return 0; 202 } |
203 bt_unit++; 204 return (BT_NREGS); 205 } 206 207 return (0); 208} 209 210/* 211 * Attach all the sub-devices we can find 212 */ 213static int 214bt_isa_attach(dev) 215 struct isa_device *dev; 216{ 217 struct bt_softc *bt; 218 bus_dma_filter_t *filter; 219 void *filter_arg; 220 bus_addr_t lowaddr; 221 222 bt = bt_softcs[dev->id_unit]; 223 if (dev->id_drq != -1) 224 isa_dmacascade(dev->id_drq); 225 226 /* Allocate our parent dmatag */ 227 filter = NULL; 228 filter_arg = NULL; 229 lowaddr = BUS_SPACE_MAXADDR_24BIT; 230 if (bt->model[0] == '4') { 231 /* 232 * This is a VL adapter. Typically, VL devices have access 233 * to the full 32bit address space. On BT-445S adapters 234 * prior to revision E, there is a hardware bug that causes 235 * corruption of transfers to/from addresses in the range of 236 * the BIOS modulo 16MB. The only properly functioning 237 * BT-445S Host Adapters have firmware version 3.37. 238 * If we encounter one of these adapters and the BIOS is 239 * installed, install a filter function for our bus_dma_map 240 * that will catch these accesses and bounce them to a safe 241 * region of memory. 242 */ 243 if (bt->bios_addr != 0 244 && strcmp(bt->model, "445S") == 0 245 && strcmp(bt->firmware_ver, "3.37") < 0) { 246 filter = btvlbouncefilter; 247 filter_arg = bt; 248 } else { 249 lowaddr = BUS_SPACE_MAXADDR_32BIT; 250 } 251 } 252 253 /* XXX Should be a child of the ISA or VL bus dma tag */ 254 if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0, 255 lowaddr, /*highaddr*/BUS_SPACE_MAXADDR, 256 filter, filter_arg, 257 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 258 /*nsegments*/BUS_SPACE_UNRESTRICTED, 259 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 260 /*flags*/0, &bt->parent_dmat) != 0) { 261 bt_free(bt); 262 return (-1); 263 } 264 265 if (bt_init(bt)) { 266 bt_free(bt); 267 return (-1); 268 } 269 270 if (lowaddr != BUS_SPACE_MAXADDR_32BIT) { 271 /* DMA tag for our sense buffers */ 272 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, 273 /*boundary*/0, 274 /*lowaddr*/BUS_SPACE_MAXADDR, 275 /*highaddr*/BUS_SPACE_MAXADDR, 276 /*filter*/NULL, /*filterarg*/NULL, 277 bt->max_ccbs 278 * sizeof(struct scsi_sense_data), 279 /*nsegments*/1, 280 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 281 /*flags*/0, &bt->sense_dmat) != 0) { 282 bt_free(bt); 283 return (-1); 284 } 285 286 bt->init_level++; 287 288 /* Allocation of sense buffers */ 289 if (bus_dmamem_alloc(bt->sense_dmat, 290 (void **)&bt->sense_buffers, 291 BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) { 292 bt_free(bt); 293 return (-1); 294 } 295 296 bt->init_level++; 297 298 /* And permanently map them */ 299 bus_dmamap_load(bt->sense_dmat, bt->sense_dmamap, 300 bt->sense_buffers, 301 bt->max_ccbs * sizeof(*bt->sense_buffers), 302 btmapsensebuffers, bt, /*flags*/0); 303 304 bt->init_level++; 305 } 306 307 return (bt_attach(bt)); 308} 309 310/* 311 * Handle an ISA interrupt. 312 * XXX should go away as soon as ISA interrupt handlers 313 * take a (void *) arg. 314 */ 315static void 316bt_isa_intr(void *unit) 317{ 318 struct bt_softc* arg = bt_softcs[(int)unit]; 319 bt_intr((void *)arg); 320} 321 322#define BIOS_MAP_SIZE (16 * 1024) 323 324static int 325btvlbouncefilter(void *arg, bus_addr_t addr) 326{ 327 struct bt_softc *bt; 328 329 bt = (struct bt_softc *)arg; 330 331 addr &= BUS_SPACE_MAXADDR_24BIT; 332 333 if (addr == 0 334 || (addr >= bt->bios_addr 335 && addr < (bt->bios_addr + BIOS_MAP_SIZE))) 336 return (1); 337 return (0); 338} 339 340static void 341btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error) 342{ 343 struct bt_softc* bt; 344 345 bt = (struct bt_softc*)arg; 346 bt->sense_buffers_physbase = segs->ds_addr; 347}
|