adv_eisa.c revision 49860
1/* 2 * Device probe and attach routines for the following 3 * Advanced Systems Inc. SCSI controllers: 4 * 5 * Single Channel Products: 6 * ABP742 - Bus-Master EISA (240 CDB) 7 * 8 * Dual Channel Products: 9 * ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel) 10 * 11 * Copyright (c) 1997 Justin Gibbs. 12 * All rights reserved. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions, and the following disclaimer, 19 * without modification, immediately at the beginning of the file. 20 * 2. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 27 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * $Id: adv_eisa.c,v 1.5 1999/08/01 22:57:08 mdodd Exp $ 36 */ 37 38#include "eisa.h" 39#if NEISA > 0 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/kernel.h> 44#include <sys/module.h> 45#include <sys/bus.h> 46 47#include <machine/bus_pio.h> 48#include <machine/bus.h> 49#include <machine/resource.h> 50#include <sys/rman.h> 51 52#include <i386/eisa/eisaconf.h> 53 54#include <dev/advansys/advansys.h> 55 56#define EISA_DEVICE_ID_ADVANSYS_740 0x04507400 57#define EISA_DEVICE_ID_ADVANSYS_750 0x04507500 58 59#define ADV_EISA_SLOT_OFFSET 0xc00 60#define ADV_EISA_OFFSET_CHAN1 0x30 61#define ADV_EISA_OFFSET_CHAN2 0x50 62#define ADV_EISA_IOSIZE 0x100 63 64#define ADV_EISA_ROM_BIOS_ADDR_REG 0x86 65#define ADV_EISA_IRQ_BURST_LEN_REG 0x87 66#define ADV_EISA_IRQ_MASK 0x07 67#define ADV_EISA_IRQ_10 0x00 68#define ADV_EISA_IRQ_11 0x01 69#define ADV_EISA_IRQ_12 0x02 70#define ADV_EISA_IRQ_14 0x04 71#define ADV_EISA_IRQ_15 0x05 72 73#define ADV_EISA_MAX_DMA_ADDR (0x07FFFFFFL) 74#define ADV_EISA_MAX_DMA_COUNT (0x07FFFFFFL) 75 76/* 77 * The overrun buffer shared amongst all EISA adapters. 78 */ 79static u_int8_t* overrun_buf; 80static bus_dma_tag_t overrun_dmat; 81static bus_dmamap_t overrun_dmamap; 82static bus_addr_t overrun_physbase; 83 84static const char *adveisamatch(eisa_id_t type); 85 86static const char* 87adveisamatch(eisa_id_t type) 88{ 89 switch (type & ~0xF) { 90 case EISA_DEVICE_ID_ADVANSYS_740: 91 return ("AdvanSys ABP-740/742 SCSI adapter"); 92 break; 93 case EISA_DEVICE_ID_ADVANSYS_750: 94 return ("AdvanSys ABP-750/752 SCSI adapter"); 95 break; 96 default: 97 break; 98 } 99 return (NULL); 100} 101 102static int 103adveisaprobe(device_t dev) 104{ 105 const char *desc; 106 u_int32_t iobase; 107 u_int8_t irq; 108 109 desc = adveisamatch(eisa_get_id(dev)); 110 if (!desc) 111 return (ENXIO); 112 device_set_desc(dev, desc); 113 114 iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) 115 + ADV_EISA_SLOT_OFFSET; 116 117 eisa_add_iospace(dev, iobase, ADV_EISA_IOSIZE, RESVADDR_NONE); 118 irq = inb(iobase + ADV_EISA_IRQ_BURST_LEN_REG); 119 irq &= ADV_EISA_IRQ_MASK; 120 switch (irq) { 121 case 0: 122 case 1: 123 case 2: 124 case 4: 125 case 5: 126 break; 127 default: 128 printf("adv at slot %d: illegal " 129 "irq setting %d\n", eisa_get_slot(dev), 130 irq); 131 return ENXIO; 132 } 133 eisa_add_intr(dev, irq + 10, EISA_TRIGGER_LEVEL); 134 135 return 0; 136} 137 138static int 139adveisaattach(device_t dev) 140{ 141 struct adv_softc *adv; 142 struct adv_softc *adv_b; 143 struct resource *io; 144 struct resource *irq; 145 int unit = device_get_unit(dev); 146 int rid, error; 147 void *ih; 148 149 adv_b = NULL; 150 151 rid = 0; 152 io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 153 0, ~0, 1, RF_ACTIVE); 154 if (!io) { 155 device_printf(dev, "No I/O space?!\n"); 156 return ENOMEM; 157 } 158 159 rid = 0; 160 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 161 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 162 if (!irq) { 163 device_printf(dev, "No irq?!\n"); 164 bus_release_resource(dev, SYS_RES_IOPORT, 0, io); 165 return ENOMEM; 166 167 } 168 169 switch (eisa_get_id(dev) & ~0xF) { 170 case EISA_DEVICE_ID_ADVANSYS_750: 171 adv_b = adv_alloc(unit, rman_get_bustag(io), 172 rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN2); 173 if (adv_b == NULL) 174 goto bad; 175 176 /* 177 * Allocate a parent dmatag for all tags created 178 * by the MI portions of the advansys driver 179 */ 180 /* XXX Should be a child of the PCI bus dma tag */ 181 error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, 182 /*boundary*/0, 183 /*lowaddr*/ADV_EISA_MAX_DMA_ADDR, 184 /*highaddr*/BUS_SPACE_MAXADDR, 185 /*filter*/NULL, /*filterarg*/NULL, 186 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 187 /*nsegments*/BUS_SPACE_UNRESTRICTED, 188 /*maxsegsz*/ADV_EISA_MAX_DMA_COUNT, 189 /*flags*/0, 190 &adv_b->parent_dmat); 191 192 if (error != 0) { 193 printf("%s: Could not allocate DMA tag - error %d\n", 194 adv_name(adv_b), error); 195 adv_free(adv_b); 196 goto bad; 197 } 198 199 adv_b->init_level++; 200 201 /* FALLTHROUGH */ 202 case EISA_DEVICE_ID_ADVANSYS_740: 203 adv = adv_alloc(unit, rman_get_bustag(io), 204 rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN1); 205 if (adv == NULL) { 206 if (adv_b != NULL) 207 adv_free(adv_b); 208 goto bad; 209 } 210 211 /* 212 * Allocate a parent dmatag for all tags created 213 * by the MI portions of the advansys driver 214 */ 215 /* XXX Should be a child of the PCI bus dma tag */ 216 error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, 217 /*boundary*/0, 218 /*lowaddr*/ADV_EISA_MAX_DMA_ADDR, 219 /*highaddr*/BUS_SPACE_MAXADDR, 220 /*filter*/NULL, /*filterarg*/NULL, 221 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 222 /*nsegments*/BUS_SPACE_UNRESTRICTED, 223 /*maxsegsz*/ADV_EISA_MAX_DMA_COUNT, 224 /*flags*/0, 225 &adv->parent_dmat); 226 227 if (error != 0) { 228 printf("%s: Could not allocate DMA tag - error %d\n", 229 adv_name(adv), error); 230 adv_free(adv); 231 goto bad; 232 } 233 234 adv->init_level++; 235 break; 236 default: 237 printf("adveisaattach: Unknown device type!\n"); 238 goto bad; 239 break; 240 } 241 242 if (overrun_buf == NULL) { 243 /* Need to allocate our overrun buffer */ 244 if (bus_dma_tag_create(adv->parent_dmat, 245 /*alignment*/8, 246 /*boundary*/0, 247 ADV_EISA_MAX_DMA_ADDR, 248 BUS_SPACE_MAXADDR, 249 /*filter*/NULL, 250 /*filterarg*/NULL, 251 ADV_OVERRUN_BSIZE, 252 /*nsegments*/1, 253 BUS_SPACE_MAXSIZE_32BIT, 254 /*flags*/0, 255 &overrun_dmat) != 0) { 256 adv_free(adv); 257 goto bad; 258 } 259 if (bus_dmamem_alloc(overrun_dmat, 260 (void **)&overrun_buf, 261 BUS_DMA_NOWAIT, 262 &overrun_dmamap) != 0) { 263 bus_dma_tag_destroy(overrun_dmat); 264 adv_free(adv); 265 goto bad; 266 } 267 /* And permanently map it in */ 268 bus_dmamap_load(overrun_dmat, overrun_dmamap, 269 overrun_buf, ADV_OVERRUN_BSIZE, 270 adv_map, &overrun_physbase, 271 /*flags*/0); 272 } 273 274 /* 275 * Now that we know we own the resources we need, do the 276 * card initialization. 277 */ 278 279 /* 280 * Stop the chip. 281 */ 282 ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT); 283 ADV_OUTW(adv, ADV_CHIP_STATUS, 0); 284 285 adv->chip_version = EISA_REVISION_ID(eisa_get_id(dev)) 286 + ADV_CHIP_MIN_VER_EISA - 1; 287 288 if (adv_init(adv) != 0) { 289 adv_free(adv); 290 if (adv_b != NULL) 291 adv_free(adv_b); 292 return(-1); 293 } 294 295 adv->max_dma_count = ADV_EISA_MAX_DMA_COUNT; 296 adv->max_dma_addr = ADV_EISA_MAX_DMA_ADDR; 297 298 if (adv_b != NULL) { 299 /* 300 * Stop the chip. 301 */ 302 ADV_OUTB(adv_b, ADV_CHIP_CTRL, ADV_CC_HALT); 303 ADV_OUTW(adv_b, ADV_CHIP_STATUS, 0); 304 305 adv_b->chip_version = EISA_REVISION_ID(eisa_get_id(dev)) 306 + ADV_CHIP_MIN_VER_EISA - 1; 307 308 if (adv_init(adv_b) != 0) { 309 adv_free(adv_b); 310 } else { 311 adv_b->max_dma_count = ADV_EISA_MAX_DMA_COUNT; 312 adv_b->max_dma_addr = ADV_EISA_MAX_DMA_ADDR; 313 } 314 } 315 316 /* 317 * Enable our interrupt handler. 318 */ 319 bus_setup_intr(dev, irq, INTR_TYPE_CAM, adv_intr, adv, &ih); 320 321 /* Attach sub-devices - always succeeds */ 322 adv_attach(adv); 323 if (adv_b != NULL) 324 adv_attach(adv_b); 325 326 return 0; 327 328 bad: 329 bus_release_resource(dev, SYS_RES_IOPORT, 0, io); 330 bus_release_resource(dev, SYS_RES_IRQ, 0, irq); 331 return -1; 332} 333 334static device_method_t adv_eisa_methods[] = { 335 /* Device interface */ 336 DEVMETHOD(device_probe, adveisaprobe), 337 DEVMETHOD(device_attach, adveisaattach), 338 339 { 0, 0 } 340}; 341 342static driver_t adv_eisa_driver = { 343 "adv", 344 adv_eisa_methods, 345 1, /* unused */ 346}; 347 348static devclass_t adv_devclass; 349 350DRIVER_MODULE(adv, eisa, adv_eisa_driver, adv_devclass, 0, 0); 351 352#endif /* NEISA > 0 */ 353