bt_mca.c revision 135260
1/*- 2 * Copyright (c) 1999 Matthew N. Dodd <winter@jurai.net> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD: head/sys/dev/buslogic/bt_mca.c 135260 2004-09-15 11:58:34Z phk $"); 30 31/* 32 * Written using the bt_isa/bt_pci code as a reference. 33 * 34 * Thanks to Andy Farkas <andyf@speednet.com.au> for 35 * testing and feedback. 36 */ 37 38#include <sys/types.h> 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> 42#include <sys/lock.h> 43#include <sys/mutex.h> 44 45#include <machine/cpufunc.h> 46#include <machine/md_var.h> 47 48#include <sys/module.h> 49#include <sys/bus.h> 50 51#include <machine/bus.h> 52#include <machine/resource.h> 53#include <sys/rman.h> 54 55#include <dev/mca/mca_busreg.h> 56#include <dev/mca/mca_busvar.h> 57 58#include <isa/isavar.h> 59 60#include <dev/buslogic/btreg.h> 61 62#include <cam/scsi/scsi_all.h> 63 64static struct mca_ident bt_mca_devs[] = { 65 { 0x0708, "BusLogic 32 Bit Bus Master MCA-to-SCSI Host Adapter" }, 66 { 0x0708, "BusTek BT-640A Micro Channel to SCSI Host Adapter" }, 67 { 0x0708, "Storage Dimensions SDC3211B 32-bit SCSI Host Adapter" }, 68 { 0x0709, "Storage Dimensions SDC3211F 32-bit FAST SCSI Host Adapter" }, 69 { 0, NULL }, 70}; 71 72#define BT_MCA_IOPORT_POS1 MCA_ADP_POS(MCA_POS0) 73#define BT_MCA_IOPORT_POS2 MCA_ADP_POS(MCA_POS1) 74#define BT_MCA_IOPORT_MASK1 0x10 75#define BT_MCA_IOPORT_MASK2 0x03 76#define BT_MCA_IOPORT_SIZE 0x03 77#define BT_MCA_IOPORT(pos) (0x30 + \ 78 (((u_int32_t)pos &\ 79 BT_MCA_IOPORT_MASK2) << 8) + \ 80 (((u_int32_t)pos &\ 81 BT_MCA_IOPORT_MASK1) >> 2)) 82 83#define BT_MCA_IRQ_POS MCA_ADP_POS(MCA_POS0) 84#define BT_MCA_IRQ_MASK 0x0e 85#define BT_MCA_IRQ(pos) (((pos & BT_MCA_IRQ_MASK) >> 1) + 8) 86 87#define BT_MCA_DRQ_POS MCA_ADP_POS(MCA_POS3) 88#define BT_MCA_DRQ_MASK 0x0f 89#define BT_MCA_DRQ(pos) (pos & BT_MCA_DRQ_MASK) 90 91#define BT_MCA_SCSIID_POS MCA_ADP_POS(MCA_POS2) 92#define BT_MCA_SCSIID_MASK 0xe0 93#define BT_MCA_SCSIID(pos) ((pos & BT_MCA_SCSIID_MASK) >> 5) 94 95static bus_dma_filter_t btvlbouncefilter; 96static bus_dmamap_callback_t btmapsensebuffers; 97 98static void 99bt_mca_release_resources (device_t dev) 100{ 101 struct bt_softc * bt = device_get_softc(dev); 102 103 if (bt->port) 104 bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->port); 105 if (bt->irq) 106 bus_release_resource(dev, SYS_RES_IRQ, 0, bt->irq); 107 if (bt->drq) 108 bus_release_resource(dev, SYS_RES_DRQ, 0, bt->drq); 109 110 bt_free_softc(dev); 111} 112 113#define BT_MCA_PROBE 0 114#define BT_MCA_ATTACH 1 115 116static int 117bt_mca_alloc_resources(device_t dev, int mode) 118{ 119 struct resource * io = NULL; 120 struct resource * irq = NULL; 121 struct resource * drq = NULL; 122 int rid; 123 124 rid = 0; 125 io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); 126 if (io == NULL) { 127 printf("bt_mca_alloc_resources() failed to allocate IOPORT\n"); 128 return (ENOMEM); 129 } 130 131 if (mode == BT_MCA_ATTACH) { 132 133 rid = 0; 134 irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 135 if (irq == NULL) { 136 printf("bt_mca_alloc_resources() failed to allocate IRQ\n"); 137 goto bad; 138 } 139 140 rid = 0; 141 drq = bus_alloc_resource_any(dev, SYS_RES_DRQ, &rid, RF_ACTIVE); 142 if (drq == NULL) { 143 printf("bt_mca_alloc_resources() failed to allocate DRQ\n"); 144 goto bad; 145 } 146 } 147 148 bt_init_softc(dev, io, irq, drq); 149 150 return (0); 151bad: 152 bt_mca_release_resources(dev); 153 return (ENOMEM); 154} 155 156static int 157bt_mca_probe (device_t dev) 158{ 159 const char * desc; 160 mca_id_t id = mca_get_id(dev); 161 struct bt_probe_info info; 162 u_int32_t iobase = 0; 163 u_int32_t iosize = 0; 164 u_int8_t drq = 0; 165 u_int8_t irq = 0; 166 u_int8_t pos; 167 int result; 168 169 desc = mca_match_id(id, bt_mca_devs); 170 if (!desc) 171 return (ENXIO); 172 device_set_desc(dev, desc); 173 174 pos = (mca_pos_read(dev, BT_MCA_IOPORT_POS1) & BT_MCA_IOPORT_MASK1) | 175 (mca_pos_read(dev, BT_MCA_IOPORT_POS2) & BT_MCA_IOPORT_MASK2); 176 iobase = BT_MCA_IOPORT(pos); 177 iosize = BT_MCA_IOPORT_SIZE; 178 179 pos = mca_pos_read(dev, BT_MCA_DRQ_POS); 180 drq = BT_MCA_DRQ(pos); 181 182 pos = mca_pos_read(dev, BT_MCA_IRQ_POS); 183 irq = BT_MCA_IRQ(pos); 184 185 bt_mark_probed_iop(iobase); 186 187 mca_add_iospace(dev, iobase, iosize); 188 189 /* And allocate them */ 190 bt_mca_alloc_resources(dev, BT_MCA_PROBE); 191 192 if (bt_port_probe(dev, &info) != 0) { 193 printf("bt_mca_probe: Probe failed for " 194 "card at slot %d\n", mca_get_slot(dev) + 1); 195 result = ENXIO; 196 } else { 197 mca_add_drq(dev, drq); 198 mca_add_irq(dev, irq); 199 result = 0; 200 } 201 bt_mca_release_resources(dev); 202 203 return (result); 204} 205 206static int 207bt_mca_attach (device_t dev) 208{ 209 struct bt_softc * bt = device_get_softc(dev); 210 int error = 0; 211 212 /* Allocate resources */ 213 if ((error = bt_mca_alloc_resources(dev, BT_MCA_ATTACH))) { 214 device_printf(dev, "Unable to allocate resources in bt_mca_attach()\n"); 215 return (error); 216 } 217 218 isa_dmacascade(rman_get_start(bt->drq)); 219 220 /* Allocate a dmatag for our CCB DMA maps */ 221 if (bus_dma_tag_create( /* parent */ NULL, 222 /* alignemnt */ 1, 223 /* boundary */ 0, 224 /* lowaddr */ BUS_SPACE_MAXADDR_24BIT, 225 /* highaddr */ BUS_SPACE_MAXADDR, 226 /* filter */ btvlbouncefilter, 227 /* filterarg */ bt, 228 /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 229 /* nsegments */ ~0, 230 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 231 /* flags */ 0, 232 /* lockfunc */ busdma_lock_mutex, 233 /* lockarg */ &Giant, 234 &bt->parent_dmat) != 0) { 235 bt_mca_release_resources(dev); 236 return (ENOMEM); 237 } 238 239 if (bt_init(dev)) { 240 bt_mca_release_resources(dev); 241 return (ENOMEM); 242 } 243 244 /* DMA tag for our sense buffers */ 245 if (bus_dma_tag_create( /* parent */ bt->parent_dmat, 246 /* alignment */ 1, 247 /* boundary */ 0, 248 /* lowaddr */ BUS_SPACE_MAXADDR, 249 /* highaddr */ BUS_SPACE_MAXADDR, 250 /* filter */ NULL, 251 /* filterarg */ NULL, 252 /* maxsize */ bt->max_ccbs * 253 sizeof(struct scsi_sense_data), 254 /* nsegments */ 1, 255 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 256 /* flags */ 0, 257 /* lockfunc */ busdma_lock_mutex, 258 /* lockarg */ &Giant, 259 &bt->sense_dmat) != 0) { 260 bt_mca_release_resources(dev); 261 return (ENOMEM); 262 } 263 264 bt->init_level++; 265 266 /* Allocation of sense buffers */ 267 if (bus_dmamem_alloc(bt->sense_dmat, 268 (void **)&bt->sense_buffers, 269 BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) { 270 bt_mca_release_resources(dev); 271 return (ENOMEM); 272 } 273 274 bt->init_level++; 275 276 /* And permanently map them */ 277 bus_dmamap_load(bt->sense_dmat, bt->sense_dmamap, 278 bt->sense_buffers, 279 bt->max_ccbs * sizeof(*bt->sense_buffers), 280 btmapsensebuffers, bt, /*flags*/0); 281 282 bt->init_level++; 283 284 if ((error = bt_attach(dev))) { 285 bt_mca_release_resources(dev); 286 return (error); 287 } 288 289 return (0); 290} 291 292/* 293 * This code should be shared with the ISA 294 * stubs as its exactly the same. 295 */ 296 297#define BIOS_MAP_SIZE (16 * 1024) 298 299static int 300btvlbouncefilter(void *arg, bus_addr_t addr) 301{ 302 struct bt_softc *bt; 303 304 bt = (struct bt_softc *)arg; 305 306 addr &= BUS_SPACE_MAXADDR_24BIT; 307 308 if (addr == 0 309 || (addr >= bt->bios_addr 310 && addr < (bt->bios_addr + BIOS_MAP_SIZE))) 311 return (1); 312 return (0); 313} 314 315static void 316btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error) 317{ 318 struct bt_softc* bt; 319 320 bt = (struct bt_softc*)arg; 321 bt->sense_buffers_physbase = segs->ds_addr; 322} 323 324static device_method_t bt_mca_methods[] = { 325 /* Device interface */ 326 DEVMETHOD(device_probe, bt_mca_probe), 327 DEVMETHOD(device_attach, bt_mca_attach), 328 329 { 0, 0 } 330}; 331 332static driver_t bt_mca_driver = { 333 "bt", 334 bt_mca_methods, 335 sizeof(struct bt_softc), 336}; 337 338static devclass_t bt_devclass; 339 340DRIVER_MODULE(bt, mca, bt_mca_driver, bt_devclass, 0, 0); 341