adv_eisa.c revision 166901
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 36#include <sys/cdefs.h> 37__FBSDID("$FreeBSD: head/sys/dev/advansys/adv_eisa.c 166901 2007-02-23 12:19:07Z piso $"); 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> 42#include <sys/module.h> 43#include <sys/lock.h> 44#include <sys/mutex.h> 45#include <sys/bus.h> 46 47#include <machine/bus.h> 48#include <machine/resource.h> 49#include <sys/rman.h> 50 51#include <dev/eisa/eisaconf.h> 52 53#include <dev/advansys/advansys.h> 54 55#define EISA_DEVICE_ID_ADVANSYS_740 0x04507400 56#define EISA_DEVICE_ID_ADVANSYS_750 0x04507500 57 58#define ADV_EISA_SLOT_OFFSET 0xc00 59#define ADV_EISA_OFFSET_CHAN1 0x30 60#define ADV_EISA_OFFSET_CHAN2 0x50 61#define ADV_EISA_IOSIZE 0x100 62 63#define ADV_EISA_ROM_BIOS_ADDR_REG 0x86 64#define ADV_EISA_IRQ_BURST_LEN_REG 0x87 65#define ADV_EISA_IRQ_MASK 0x07 66#define ADV_EISA_IRQ_10 0x00 67#define ADV_EISA_IRQ_11 0x01 68#define ADV_EISA_IRQ_12 0x02 69#define ADV_EISA_IRQ_14 0x04 70#define ADV_EISA_IRQ_15 0x05 71 72#define ADV_EISA_MAX_DMA_ADDR (0x07FFFFFFL) 73#define ADV_EISA_MAX_DMA_COUNT (0x07FFFFFFL) 74 75/* 76 * The overrun buffer shared amongst all EISA adapters. 77 */ 78static void* overrun_buf; 79static bus_dma_tag_t overrun_dmat; 80static bus_dmamap_t overrun_dmamap; 81static bus_addr_t overrun_physbase; 82 83static const char* 84adv_eisa_match(eisa_id_t type) 85{ 86 switch (type & ~0xF) { 87 case EISA_DEVICE_ID_ADVANSYS_740: 88 return ("AdvanSys ABP-740/742 SCSI adapter"); 89 break; 90 case EISA_DEVICE_ID_ADVANSYS_750: 91 return ("AdvanSys ABP-750/752 SCSI adapter"); 92 break; 93 default: 94 break; 95 } 96 return (NULL); 97} 98 99static int 100adv_eisa_probe(device_t dev) 101{ 102 const char *desc; 103 u_int32_t iobase; 104 u_int8_t irq; 105 106 desc = adv_eisa_match(eisa_get_id(dev)); 107 if (!desc) 108 return (ENXIO); 109 device_set_desc(dev, desc); 110 111 iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) + ADV_EISA_SLOT_OFFSET; 112 113 eisa_add_iospace(dev, iobase, ADV_EISA_IOSIZE, RESVADDR_NONE); 114 irq = inb(iobase + ADV_EISA_IRQ_BURST_LEN_REG); 115 irq &= ADV_EISA_IRQ_MASK; 116 switch (irq) { 117 case 0: 118 case 1: 119 case 2: 120 case 4: 121 case 5: 122 break; 123 default: 124 printf("adv at slot %d: illegal " 125 "irq setting %d\n", eisa_get_slot(dev), 126 irq); 127 return ENXIO; 128 } 129 eisa_add_intr(dev, irq + 10, EISA_TRIGGER_LEVEL); 130 131 return 0; 132} 133 134static int 135adv_eisa_attach(device_t dev) 136{ 137 struct adv_softc *adv; 138 struct adv_softc *adv_b; 139 struct resource *io; 140 struct resource *irq; 141 int rid, error; 142 void *ih; 143 144 adv_b = NULL; 145 146 rid = 0; 147 io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); 148 if (!io) { 149 device_printf(dev, "No I/O space?!\n"); 150 return ENOMEM; 151 } 152 153 rid = 0; 154 irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 155 RF_SHAREABLE | RF_ACTIVE); 156 if (!irq) { 157 device_printf(dev, "No irq?!\n"); 158 bus_release_resource(dev, SYS_RES_IOPORT, 0, io); 159 return ENOMEM; 160 161 } 162 163 switch (eisa_get_id(dev) & ~0xF) { 164 case EISA_DEVICE_ID_ADVANSYS_750: 165 adv_b = adv_alloc(dev, rman_get_bustag(io), 166 rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN2); 167 if (adv_b == NULL) 168 goto bad; 169 170 /* 171 * Allocate a parent dmatag for all tags created 172 * by the MI portions of the advansys driver 173 */ 174 /* XXX Should be a child of the PCI bus dma tag */ 175 error = bus_dma_tag_create( 176 /* parent */ NULL, 177 /* alignment */ 1, 178 /* boundary */ 0, 179 /* lowaddr */ ADV_EISA_MAX_DMA_ADDR, 180 /* highaddr */ BUS_SPACE_MAXADDR, 181 /* filter */ NULL, 182 /* filterarg */ NULL, 183 /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 184 /* nsegments */ ~0, 185 /* maxsegsz */ ADV_EISA_MAX_DMA_COUNT, 186 /* flags */ 0, 187 /* lockfunc */ busdma_lock_mutex, 188 /* lockarg */ &Giant, 189 &adv_b->parent_dmat); 190 191 if (error != 0) { 192 printf("%s: Could not allocate DMA tag - error %d\n", 193 adv_name(adv_b), error); 194 adv_free(adv_b); 195 goto bad; 196 } 197 198 adv_b->init_level++; 199 200 /* FALLTHROUGH */ 201 case EISA_DEVICE_ID_ADVANSYS_740: 202 adv = adv_alloc(dev, rman_get_bustag(io), 203 rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN1); 204 if (adv == NULL) { 205 if (adv_b != NULL) 206 adv_free(adv_b); 207 goto bad; 208 } 209 210 /* 211 * Allocate a parent dmatag for all tags created 212 * by the MI portions of the advansys driver 213 */ 214 /* XXX Should be a child of the PCI bus dma tag */ 215 error = bus_dma_tag_create( 216 /* parent */ NULL, 217 /* alignment */ 1, 218 /* boundary */ 0, 219 /* lowaddr */ ADV_EISA_MAX_DMA_ADDR, 220 /* highaddr */ BUS_SPACE_MAXADDR, 221 /* filter */ NULL, 222 /* filterarg */ NULL, 223 /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 224 /* nsegments */ ~0, 225 /* maxsegsz */ ADV_EISA_MAX_DMA_COUNT, 226 /* flags */ 0, 227 /* lockfunc */ busdma_lock_mutex, 228 /* lockarg */ &Giant, 229 &adv->parent_dmat); 230 231 if (error != 0) { 232 printf("%s: Could not allocate DMA tag - error %d\n", 233 adv_name(adv), error); 234 adv_free(adv); 235 goto bad; 236 } 237 238 adv->init_level++; 239 break; 240 default: 241 printf("adveisaattach: Unknown device type!\n"); 242 goto bad; 243 break; 244 } 245 246 if (overrun_buf == NULL) { 247 /* Need to allocate our overrun buffer */ 248 if (bus_dma_tag_create( 249 /* parent */ adv->parent_dmat, 250 /* alignment */ 8, 251 /* boundary */ 0, 252 /* lowaddr */ ADV_EISA_MAX_DMA_ADDR, 253 /* highaddr */ BUS_SPACE_MAXADDR, 254 /* filter */ NULL, 255 /* filterarg */ NULL, 256 /* maxsize */ ADV_OVERRUN_BSIZE, 257 /* nsegments */ 1, 258 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 259 /* flags */ 0, 260 /* lockfunc */ busdma_lock_mutex, 261 /* lockarg */ &Giant, 262 &overrun_dmat) != 0) { 263 adv_free(adv); 264 goto bad; 265 } 266 if (bus_dmamem_alloc(overrun_dmat, 267 &overrun_buf, 268 BUS_DMA_NOWAIT, 269 &overrun_dmamap) != 0) { 270 bus_dma_tag_destroy(overrun_dmat); 271 adv_free(adv); 272 goto bad; 273 } 274 /* And permanently map it in */ 275 bus_dmamap_load(overrun_dmat, overrun_dmamap, 276 overrun_buf, ADV_OVERRUN_BSIZE, 277 adv_map, &overrun_physbase, 278 /*flags*/0); 279 } 280 281 /* 282 * Now that we know we own the resources we need, do the 283 * card initialization. 284 */ 285 286 /* 287 * Stop the chip. 288 */ 289 ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT); 290 ADV_OUTW(adv, ADV_CHIP_STATUS, 0); 291 292 adv->chip_version = EISA_REVISION_ID(eisa_get_id(dev)) 293 + ADV_CHIP_MIN_VER_EISA - 1; 294 295 if (adv_init(adv) != 0) { 296 adv_free(adv); 297 if (adv_b != NULL) 298 adv_free(adv_b); 299 return(-1); 300 } 301 302 adv->max_dma_count = ADV_EISA_MAX_DMA_COUNT; 303 adv->max_dma_addr = ADV_EISA_MAX_DMA_ADDR; 304 305 if (adv_b != NULL) { 306 /* 307 * Stop the chip. 308 */ 309 ADV_OUTB(adv_b, ADV_CHIP_CTRL, ADV_CC_HALT); 310 ADV_OUTW(adv_b, ADV_CHIP_STATUS, 0); 311 312 adv_b->chip_version = EISA_REVISION_ID(eisa_get_id(dev)) 313 + ADV_CHIP_MIN_VER_EISA - 1; 314 315 if (adv_init(adv_b) != 0) { 316 adv_free(adv_b); 317 } else { 318 adv_b->max_dma_count = ADV_EISA_MAX_DMA_COUNT; 319 adv_b->max_dma_addr = ADV_EISA_MAX_DMA_ADDR; 320 } 321 } 322 323 /* 324 * Enable our interrupt handler. 325 */ 326 bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY, NULL, adv_intr, 327 adv, &ih); 328 329 /* Attach sub-devices - always succeeds */ 330 adv_attach(adv); 331 if (adv_b != NULL) 332 adv_attach(adv_b); 333 334 return 0; 335 336 bad: 337 bus_release_resource(dev, SYS_RES_IOPORT, 0, io); 338 bus_release_resource(dev, SYS_RES_IRQ, 0, irq); 339 return -1; 340} 341 342static device_method_t adv_eisa_methods[] = { 343 /* Device interface */ 344 DEVMETHOD(device_probe, adv_eisa_probe), 345 DEVMETHOD(device_attach, adv_eisa_attach), 346 { 0, 0 } 347}; 348 349static driver_t adv_eisa_driver = { 350 "adv", adv_eisa_methods, sizeof(struct adv_softc) 351}; 352 353static devclass_t adv_eisa_devclass; 354DRIVER_MODULE(adv, eisa, adv_eisa_driver, adv_eisa_devclass, 0, 0); 355MODULE_DEPEND(adv, eisa, 1, 1, 1); 356