bt_mca.c revision 112782
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 * $FreeBSD: head/sys/dev/buslogic/bt_mca.c 112782 2003-03-29 09:46:10Z mdodd $ 27 */ 28 29/* 30 * Written using the bt_isa/bt_pci code as a reference. 31 * 32 * Thanks to Andy Farkas <andyf@speednet.com.au> for 33 * testing and feedback. 34 */ 35 36#include <sys/types.h> 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/kernel.h> 40 41#include <machine/cpufunc.h> 42#include <machine/md_var.h> 43 44#include <sys/module.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/mca/mca_busreg.h> 52#include <dev/mca/mca_busvar.h> 53 54#include <i386/isa/isa_dma.h> 55 56#include <dev/buslogic/btreg.h> 57 58#include <cam/scsi/scsi_all.h> 59 60static struct mca_ident bt_mca_devs[] = { 61 { 0x0708, "BusLogic 32 Bit Bus Master MCA-to-SCSI Host Adapter" }, 62 { 0x0708, "BusTek BT-640A Micro Channel to SCSI Host Adapter" }, 63 { 0x0708, "Storage Dimensions SDC3211B 32-bit SCSI Host Adapter" }, 64 { 0x0709, "Storage Dimensions SDC3211F 32-bit FAST SCSI Host Adapter" }, 65 { 0, NULL }, 66}; 67 68#define BT_MCA_IOPORT_POS1 MCA_ADP_POS(MCA_POS0) 69#define BT_MCA_IOPORT_POS2 MCA_ADP_POS(MCA_POS1) 70#define BT_MCA_IOPORT_MASK1 0x10 71#define BT_MCA_IOPORT_MASK2 0x03 72#define BT_MCA_IOPORT_SIZE 0x03 73#define BT_MCA_IOPORT(pos) (0x30 + \ 74 (((u_int32_t)pos &\ 75 BT_MCA_IOPORT_MASK2) << 8) + \ 76 (((u_int32_t)pos &\ 77 BT_MCA_IOPORT_MASK1) >> 2)) 78 79#define BT_MCA_IRQ_POS MCA_ADP_POS(MCA_POS0) 80#define BT_MCA_IRQ_MASK 0x0e 81#define BT_MCA_IRQ(pos) (((pos & BT_MCA_IRQ_MASK) >> 1) + 8) 82 83#define BT_MCA_DRQ_POS MCA_ADP_POS(MCA_POS3) 84#define BT_MCA_DRQ_MASK 0x0f 85#define BT_MCA_DRQ(pos) (pos & BT_MCA_DRQ_MASK) 86 87#define BT_MCA_SCSIID_POS MCA_ADP_POS(MCA_POS2) 88#define BT_MCA_SCSIID_MASK 0xe0 89#define BT_MCA_SCSIID(pos) ((pos & BT_MCA_SCSIID_MASK) >> 5) 90 91static bus_dma_filter_t btvlbouncefilter; 92static bus_dmamap_callback_t btmapsensebuffers; 93 94static void 95bt_mca_release_resources (device_t dev) 96{ 97 struct bt_softc * bt = device_get_softc(dev); 98 99 if (bt->port) 100 bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->port); 101 if (bt->irq) 102 bus_release_resource(dev, SYS_RES_IRQ, 0, bt->irq); 103 if (bt->drq) 104 bus_release_resource(dev, SYS_RES_DRQ, 0, bt->drq); 105 106 bt_free_softc(dev); 107} 108 109#define BT_MCA_PROBE 0 110#define BT_MCA_ATTACH 1 111 112static int 113bt_mca_alloc_resources(device_t dev, int mode) 114{ 115 struct resource * io = NULL; 116 struct resource * irq = NULL; 117 struct resource * drq = NULL; 118 int rid; 119 120 rid = 0; 121 io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 122 0, ~0, 1, RF_ACTIVE); 123 if (io == NULL) { 124 printf("bt_mca_alloc_resources() failed to allocate IOPORT\n"); 125 return (ENOMEM); 126 } 127 128 if (mode == BT_MCA_ATTACH) { 129 130 rid = 0; 131 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 132 0, ~0, 1, RF_ACTIVE); 133 if (irq == NULL) { 134 printf("bt_mca_alloc_resources() failed to allocate IRQ\n"); 135 goto bad; 136 } 137 138 rid = 0; 139 drq = bus_alloc_resource(dev, SYS_RES_DRQ, &rid, 140 0, ~0, 1, RF_ACTIVE); 141 if (drq == NULL) { 142 printf("bt_mca_alloc_resources() failed to allocate DRQ\n"); 143 goto bad; 144 } 145 } 146 147 bt_init_softc(dev, io, irq, drq); 148 149 return (0); 150bad: 151 bt_mca_release_resources(dev); 152 return (ENOMEM); 153} 154 155static int 156bt_mca_probe (device_t dev) 157{ 158 const char * desc; 159 mca_id_t id = mca_get_id(dev); 160 struct bt_probe_info info; 161 u_int32_t iobase = 0; 162 u_int32_t iosize = 0; 163 u_int8_t drq = 0; 164 u_int8_t irq = 0; 165 u_int8_t pos; 166 int result; 167 168 desc = mca_match_id(id, bt_mca_devs); 169 if (!desc) 170 return (ENXIO); 171 device_set_desc(dev, desc); 172 173 pos = (mca_pos_read(dev, BT_MCA_IOPORT_POS1) & BT_MCA_IOPORT_MASK1) | 174 (mca_pos_read(dev, BT_MCA_IOPORT_POS2) & BT_MCA_IOPORT_MASK2); 175 iobase = BT_MCA_IOPORT(pos); 176 iosize = BT_MCA_IOPORT_SIZE; 177 178 pos = mca_pos_read(dev, BT_MCA_DRQ_POS); 179 drq = BT_MCA_DRQ(pos); 180 181 pos = mca_pos_read(dev, BT_MCA_IRQ_POS); 182 irq = BT_MCA_IRQ(pos); 183 184 bt_mark_probed_iop(iobase); 185 186 mca_add_iospace(dev, iobase, iosize); 187 188 /* And allocate them */ 189 bt_mca_alloc_resources(dev, BT_MCA_PROBE); 190 191 if (bt_port_probe(dev, &info) != 0) { 192 printf("bt_mca_probe: Probe failed for " 193 "card at slot %d\n", mca_get_slot(dev) + 1); 194 result = ENXIO; 195 } else { 196 mca_add_drq(dev, drq); 197 mca_add_irq(dev, irq); 198 result = 0; 199 } 200 bt_mca_release_resources(dev); 201 202 return (result); 203} 204 205static int 206bt_mca_attach (device_t dev) 207{ 208 struct bt_softc * bt = device_get_softc(dev); 209 int error = 0; 210 211 /* Allocate resources */ 212 if ((error = bt_mca_alloc_resources(dev, BT_MCA_ATTACH))) { 213 device_printf(dev, "Unable to allocate resources in bt_mca_attach()\n"); 214 return (error); 215 } 216 217 isa_dmacascade(rman_get_start(bt->drq)); 218 219 /* Allocate a dmatag for our CCB DMA maps */ 220 if (bus_dma_tag_create( /* parent */ NULL, 221 /* alignemnt */ 1, 222 /* boundary */ 0, 223 /* lowaddr */ BUS_SPACE_MAXADDR_24BIT, 224 /* highaddr */ BUS_SPACE_MAXADDR, 225 /* filter */ btvlbouncefilter, 226 /* filterarg */ bt, 227 /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 228 /* nsegments */ ~0, 229 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 230 /* flags */ 0, 231 &bt->parent_dmat) != 0) { 232 bt_mca_release_resources(dev); 233 return (ENOMEM); 234 } 235 236 if (bt_init(dev)) { 237 bt_mca_release_resources(dev); 238 return (ENOMEM); 239 } 240 241 /* DMA tag for our sense buffers */ 242 if (bus_dma_tag_create( /* parent */ bt->parent_dmat, 243 /* alignment */ 1, 244 /* boundary */ 0, 245 /* lowaddr */ BUS_SPACE_MAXADDR, 246 /* highaddr */ BUS_SPACE_MAXADDR, 247 /* filter */ NULL, 248 /* filterarg */ NULL, 249 /* maxsize */ bt->max_ccbs * 250 sizeof(struct scsi_sense_data), 251 /* nsegments */ 1, 252 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 253 /* flags */ 0, 254 &bt->sense_dmat) != 0) { 255 bt_mca_release_resources(dev); 256 return (ENOMEM); 257 } 258 259 bt->init_level++; 260 261 /* Allocation of sense buffers */ 262 if (bus_dmamem_alloc(bt->sense_dmat, 263 (void **)&bt->sense_buffers, 264 BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) { 265 bt_mca_release_resources(dev); 266 return (ENOMEM); 267 } 268 269 bt->init_level++; 270 271 /* And permanently map them */ 272 bus_dmamap_load(bt->sense_dmat, bt->sense_dmamap, 273 bt->sense_buffers, 274 bt->max_ccbs * sizeof(*bt->sense_buffers), 275 btmapsensebuffers, bt, /*flags*/0); 276 277 bt->init_level++; 278 279 if ((error = bt_attach(dev))) { 280 bt_mca_release_resources(dev); 281 return (error); 282 } 283 284 return (0); 285} 286 287/* 288 * This code should be shared with the ISA 289 * stubs as its exactly the same. 290 */ 291 292#define BIOS_MAP_SIZE (16 * 1024) 293 294static int 295btvlbouncefilter(void *arg, bus_addr_t addr) 296{ 297 struct bt_softc *bt; 298 299 bt = (struct bt_softc *)arg; 300 301 addr &= BUS_SPACE_MAXADDR_24BIT; 302 303 if (addr == 0 304 || (addr >= bt->bios_addr 305 && addr < (bt->bios_addr + BIOS_MAP_SIZE))) 306 return (1); 307 return (0); 308} 309 310static void 311btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error) 312{ 313 struct bt_softc* bt; 314 315 bt = (struct bt_softc*)arg; 316 bt->sense_buffers_physbase = segs->ds_addr; 317} 318 319static device_method_t bt_mca_methods[] = { 320 /* Device interface */ 321 DEVMETHOD(device_probe, bt_mca_probe), 322 DEVMETHOD(device_attach, bt_mca_attach), 323 324 { 0, 0 } 325}; 326 327static driver_t bt_mca_driver = { 328 "bt", 329 bt_mca_methods, 330 sizeof(struct bt_softc), 331}; 332 333static devclass_t bt_devclass; 334 335DRIVER_MODULE(bt, mca, bt_mca_driver, bt_devclass, 0, 0); 336