adv_eisa.c revision 232883
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 232883 2012-03-12 19:29:35Z scottl $"); 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 error = bus_dma_tag_create( 175 /* parent */ bus_get_dma_tag(dev), 176 /* alignment */ 1, 177 /* boundary */ 0, 178 /* lowaddr */ ADV_EISA_MAX_DMA_ADDR, 179 /* highaddr */ BUS_SPACE_MAXADDR, 180 /* filter */ NULL, 181 /* filterarg */ NULL, 182 /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 183 /* nsegments */ ~0, 184 /* maxsegsz */ ADV_EISA_MAX_DMA_COUNT, 185 /* flags */ 0, 186 /* lockfunc */ busdma_lock_mutex, 187 /* lockarg */ &Giant, 188 &adv_b->parent_dmat); 189 190 if (error != 0) { 191 printf("%s: Could not allocate DMA tag - error %d\n", 192 adv_name(adv_b), error); 193 adv_free(adv_b); 194 goto bad; 195 } 196 197 adv_b->init_level++; 198 199 /* FALLTHROUGH */ 200 case EISA_DEVICE_ID_ADVANSYS_740: 201 adv = adv_alloc(dev, rman_get_bustag(io), 202 rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN1); 203 if (adv == NULL) { 204 if (adv_b != NULL) 205 adv_free(adv_b); 206 goto bad; 207 } 208 209 /* 210 * Allocate a parent dmatag for all tags created 211 * by the MI portions of the advansys driver 212 */ 213 error = bus_dma_tag_create( 214 /* parent */ bus_get_dma_tag(dev), 215 /* alignment */ 1, 216 /* boundary */ 0, 217 /* lowaddr */ ADV_EISA_MAX_DMA_ADDR, 218 /* highaddr */ BUS_SPACE_MAXADDR, 219 /* filter */ NULL, 220 /* filterarg */ NULL, 221 /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 222 /* nsegments */ ~0, 223 /* maxsegsz */ ADV_EISA_MAX_DMA_COUNT, 224 /* flags */ 0, 225 /* lockfunc */ busdma_lock_mutex, 226 /* lockarg */ &Giant, 227 &adv->parent_dmat); 228 229 if (error != 0) { 230 printf("%s: Could not allocate DMA tag - error %d\n", 231 adv_name(adv), error); 232 adv_free(adv); 233 goto bad; 234 } 235 236 adv->init_level++; 237 break; 238 default: 239 printf("adveisaattach: Unknown device type!\n"); 240 goto bad; 241 break; 242 } 243 244 if (overrun_buf == NULL) { 245 /* Need to allocate our overrun buffer */ 246 if (bus_dma_tag_create( 247 /* parent */ adv->parent_dmat, 248 /* alignment */ 8, 249 /* boundary */ 0, 250 /* lowaddr */ ADV_EISA_MAX_DMA_ADDR, 251 /* highaddr */ BUS_SPACE_MAXADDR, 252 /* filter */ NULL, 253 /* filterarg */ NULL, 254 /* maxsize */ ADV_OVERRUN_BSIZE, 255 /* nsegments */ 1, 256 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 257 /* flags */ 0, 258 /* lockfunc */ busdma_lock_mutex, 259 /* lockarg */ &Giant, 260 &overrun_dmat) != 0) { 261 adv_free(adv); 262 goto bad; 263 } 264 if (bus_dmamem_alloc(overrun_dmat, 265 &overrun_buf, 266 BUS_DMA_NOWAIT, 267 &overrun_dmamap) != 0) { 268 bus_dma_tag_destroy(overrun_dmat); 269 adv_free(adv); 270 goto bad; 271 } 272 /* And permanently map it in */ 273 bus_dmamap_load(overrun_dmat, overrun_dmamap, 274 overrun_buf, ADV_OVERRUN_BSIZE, 275 adv_map, &overrun_physbase, 276 /*flags*/0); 277 } 278 279 /* 280 * Now that we know we own the resources we need, do the 281 * card initialization. 282 */ 283 284 /* 285 * Stop the chip. 286 */ 287 ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT); 288 ADV_OUTW(adv, ADV_CHIP_STATUS, 0); 289 290 adv->chip_version = EISA_REVISION_ID(eisa_get_id(dev)) 291 + ADV_CHIP_MIN_VER_EISA - 1; 292 293 if (adv_init(adv) != 0) { 294 adv_free(adv); 295 if (adv_b != NULL) 296 adv_free(adv_b); 297 return(-1); 298 } 299 300 adv->max_dma_count = ADV_EISA_MAX_DMA_COUNT; 301 adv->max_dma_addr = ADV_EISA_MAX_DMA_ADDR; 302 303 if (adv_b != NULL) { 304 /* 305 * Stop the chip. 306 */ 307 ADV_OUTB(adv_b, ADV_CHIP_CTRL, ADV_CC_HALT); 308 ADV_OUTW(adv_b, ADV_CHIP_STATUS, 0); 309 310 adv_b->chip_version = EISA_REVISION_ID(eisa_get_id(dev)) 311 + ADV_CHIP_MIN_VER_EISA - 1; 312 313 if (adv_init(adv_b) != 0) { 314 adv_free(adv_b); 315 } else { 316 adv_b->max_dma_count = ADV_EISA_MAX_DMA_COUNT; 317 adv_b->max_dma_addr = ADV_EISA_MAX_DMA_ADDR; 318 } 319 } 320 321 /* 322 * Enable our interrupt handler. 323 */ 324 bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY, NULL, adv_intr, 325 adv, &ih); 326 327 /* Attach sub-devices - always succeeds */ 328 adv_attach(adv); 329 if (adv_b != NULL) 330 adv_attach(adv_b); 331 332 return 0; 333 334 bad: 335 bus_release_resource(dev, SYS_RES_IOPORT, 0, io); 336 bus_release_resource(dev, SYS_RES_IRQ, 0, irq); 337 return -1; 338} 339 340static device_method_t adv_eisa_methods[] = { 341 /* Device interface */ 342 DEVMETHOD(device_probe, adv_eisa_probe), 343 DEVMETHOD(device_attach, adv_eisa_attach), 344 { 0, 0 } 345}; 346 347static driver_t adv_eisa_driver = { 348 "adv", adv_eisa_methods, sizeof(struct adv_softc) 349}; 350 351static devclass_t adv_eisa_devclass; 352DRIVER_MODULE(adv, eisa, adv_eisa_driver, adv_eisa_devclass, 0, 0); 353MODULE_DEPEND(adv, eisa, 1, 1, 1); 354