ct_isa.c revision 84719
1/* $FreeBSD: head/sys/dev/ct/ct_isa.c 84719 2001-10-09 15:30:19Z nyan $ */ 2/* $NecBSD: ct_isa.c,v 1.6 1999/07/26 06:32:01 honda Exp $ */ 3/* $NetBSD$ */ 4 5/* 6 * [NetBSD for NEC PC-98 series] 7 * Copyright (c) 1995, 1996, 1997, 1998 8 * NetBSD/pc98 porting staff. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34#define SCSIBUS_RESCAN 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/kernel.h> 39#include <sys/disklabel.h> 40#include <sys/bio.h> 41#include <sys/buf.h> 42#include <sys/queue.h> 43#include <sys/malloc.h> 44#include <sys/device_port.h> 45#include <sys/errno.h> 46 47#include <vm/vm.h> 48 49#ifdef __NetBSD__ 50#include <machine/bus.h> 51#include <machine/intr.h> 52 53#include <dev/scsipi/scsi_all.h> 54#include <dev/scsipi/scsipi_all.h> 55#include <dev/scsipi/scsiconf.h> 56#include <dev/scsipi/scsi_disk.h> 57 58#include <dev/isa/isareg.h> 59#include <dev/isa/isavar.h> 60#include <dev/isa/isadmavar.h> 61 62#include <machine/dvcfg.h> 63#include <machine/physio_proc.h> 64#include <machine/syspmgr.h> 65 66#include <i386/Cbus/dev/scsi_low.h> 67 68#include <dev/ic/wd33c93reg.h> 69#include <i386/Cbus/dev/ct/ctvar.h> 70#include <i386/Cbus/dev/ct/bshwvar.h> 71#endif /* __NetBSD__ */ 72 73#ifdef __FreeBSD__ 74#include <machine/bus.h> 75#include <machine/resource.h> 76#include <sys/bus.h> 77#include <sys/rman.h> 78#include <machine/md_var.h> 79 80#include <pc98/pc98/pc98.h> 81#include <isa/isavar.h> 82 83#include <machine/dvcfg.h> 84#include <machine/physio_proc.h> 85 86#include <cam/scsi/scsi_low.h> 87 88#include <dev/ic/wd33c93reg.h> 89#include <dev/ct/ctvar.h> 90#include <dev/ct/bshwvar.h> 91#endif /* __FreeBSD__ */ 92 93#define BSHW_IOSZ 0x08 94#define BSHW_IOBASE 0xcc0 95#define BSHW_MEMSZ (PAGE_SIZE * 2) 96 97static int ct_isa_match(device_t); 98static int ct_isa_attach(device_t); 99static int ct_space_map(device_t, struct bshw *, 100 struct resource **, struct resource **); 101static void ct_space_unmap(device_t, struct ct_softc *); 102static struct bshw *ct_find_hw(device_t); 103static void ct_dmamap(void *, bus_dma_segment_t *, int, int); 104static void ct_isa_bus_access_weight __P((struct ct_bus_access_handle *)); 105static void ct_isa_dmasync_before __P((struct ct_softc *)); 106static void ct_isa_dmasync_after __P((struct ct_softc *)); 107 108struct ct_isa_softc { 109 struct ct_softc sc_ct; 110 struct bshw_softc sc_bshw; 111}; 112 113static struct isa_pnp_id ct_pnp_ids[] = { 114 { 0x0100e7b1, "Logitec LHA-301" }, 115 { 0x110154dc, "I-O DATA SC-98III" }, 116 { 0x4120acb4, "MELCO IFC-NN" }, 117 { 0, NULL } 118}; 119 120static device_method_t ct_isa_methods[] = { 121 /* Device interface */ 122 DEVMETHOD(device_probe, ct_isa_match), 123 DEVMETHOD(device_attach, ct_isa_attach), 124 { 0, 0 } 125}; 126 127static driver_t ct_isa_driver = { 128 "ct", ct_isa_methods, sizeof(struct ct_isa_softc), 129}; 130 131static devclass_t ct_devclass; 132 133DRIVER_MODULE(ct, isa, ct_isa_driver, ct_devclass, 0, 0); 134 135static int 136ct_isa_match(device_t dev) 137{ 138 struct bshw *hw; 139 struct resource *port_res, *mem_res; 140 struct ct_bus_access_handle ch; 141 int rv; 142 143 if (ISA_PNP_PROBE(device_get_parent(dev), dev, ct_pnp_ids) == ENXIO) 144 return ENXIO; 145 146 if (isa_get_port(dev) == -1) 147 bus_set_resource(dev, SYS_RES_IOPORT, 0, 148 BSHW_IOBASE, BSHW_IOSZ); 149 150 if ((hw = ct_find_hw(dev)) == NULL) 151 return ENXIO; 152 if (ct_space_map(dev, hw, &port_res, &mem_res) != 0) 153 return ENXIO; 154 155 bzero(&ch, sizeof(ch)); 156 ch.ch_iot = rman_get_bustag(port_res); 157 ch.ch_ioh = rman_get_bushandle(port_res), 158 ch.ch_bus_weight = ct_isa_bus_access_weight; 159 160 rv = ctprobesubr(&ch, 0, BSHW_DEFAULT_HOSTID, 161 BSHW_DEFAULT_CHIPCLK, NULL); 162 if (rv != 0) 163 { 164 struct bshw_softc bshw_tab; 165 struct bshw_softc *bs = &bshw_tab; 166 167 memset(bs, 0, sizeof(*bs)); 168 bshw_read_settings(&ch, bs); 169 bus_set_resource(dev, SYS_RES_IRQ, 0, bs->sc_irq, 1); 170 bus_set_resource(dev, SYS_RES_DRQ, 0, bs->sc_drq, 1); 171 } 172 173 bus_release_resource(dev, SYS_RES_IOPORT, 0, port_res); 174 if (mem_res != NULL) 175 bus_release_resource(dev, SYS_RES_MEMORY, 0, mem_res); 176 177 if (rv != 0) 178 return 0; 179 return ENXIO; 180} 181 182static int 183ct_isa_attach(device_t dev) 184{ 185 struct ct_isa_softc *pct = device_get_softc(dev); 186 struct ct_softc *ct = &pct->sc_ct; 187 struct ct_bus_access_handle *chp = &ct->sc_ch; 188 struct scsi_low_softc *slp = &ct->sc_sclow; 189 struct bshw_softc *bs = &pct->sc_bshw; 190 struct bshw *hw; 191 int irq_rid, drq_rid, chiprev; 192 u_int8_t *vaddr; 193 bus_addr_t addr; 194 intrmask_t s; 195 196 hw = ct_find_hw(dev); 197 if (ct_space_map(dev, hw, &ct->port_res, &ct->mem_res) != 0) { 198 device_printf(dev, "bus io mem map failed\n"); 199 return ENXIO; 200 } 201 202 bzero(chp, sizeof(*chp)); 203 chp->ch_iot = rman_get_bustag(ct->port_res); 204 chp->ch_ioh = rman_get_bushandle(ct->port_res); 205 if (ct->mem_res) { 206 chp->ch_memt = rman_get_bustag(ct->mem_res); 207 chp->ch_memh = rman_get_bushandle(ct->mem_res); 208 } 209 chp->ch_bus_weight = ct_isa_bus_access_weight; 210 211 irq_rid = 0; 212 ct->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &irq_rid, 0, ~0, 213 1, RF_ACTIVE); 214 drq_rid = 0; 215 ct->drq_res = bus_alloc_resource(dev, SYS_RES_DRQ, &drq_rid, 0, ~0, 216 1, RF_ACTIVE); 217 if (ct->irq_res == NULL || ct->drq_res == NULL) { 218 ct_space_unmap(dev, ct); 219 return ENXIO; 220 } 221 222 if (ctprobesubr(chp, 0, BSHW_DEFAULT_HOSTID, 223 BSHW_DEFAULT_CHIPCLK, &chiprev) == 0) 224 { 225 device_printf(dev, "hardware missing\n"); 226 ct_space_unmap(dev, ct); 227 return ENXIO; 228 } 229 230 /* setup DMA map */ 231 if (bus_dma_tag_create(NULL, 1, 0, 232 BUS_SPACE_MAXADDR_24BIT, BUS_SPACE_MAXADDR, 233 NULL, NULL, MAXBSIZE, 1, 234 BUS_SPACE_MAXSIZE_32BIT, 235 BUS_DMA_ALLOCNOW, &ct->sc_dmat) != 0) { 236 device_printf(dev, "can't set up ISA DMA map\n"); 237 ct_space_unmap(dev, ct); 238 return ENXIO; 239 } 240 241 if (bus_dmamem_alloc(ct->sc_dmat, (void **)&vaddr, BUS_DMA_NOWAIT, 242 &ct->sc_dmamapt) != 0) { 243 device_printf(dev, "can't set up ISA DMA map\n"); 244 ct_space_unmap(dev, ct); 245 return ENXIO; 246 } 247 248 bus_dmamap_load(ct->sc_dmat, ct->sc_dmamapt, vaddr, MAXBSIZE, 249 ct_dmamap, &addr, 0); 250 251 /* setup machdep softc */ 252 bs->sc_hw = hw; 253 bs->sc_io_control = 0; 254 bs->sc_bounce_phys = (u_int8_t *)addr; 255 bs->sc_bounce_addr = vaddr; 256 bs->sc_bounce_size = MAXBSIZE; 257 bs->sc_minphys = (1 << 24); 258 bs->sc_dmasync_before = ct_isa_dmasync_before; 259 bs->sc_dmasync_after = ct_isa_dmasync_after; 260 bshw_read_settings(chp, bs); 261 262 /* setup ct driver softc */ 263 ct->ct_hw = bs; 264 ct->ct_dma_xfer_start = bshw_dma_xfer_start; 265 ct->ct_pio_xfer_start = bshw_smit_xfer_start; 266 ct->ct_dma_xfer_stop = bshw_dma_xfer_stop; 267 ct->ct_pio_xfer_stop = bshw_smit_xfer_stop; 268 ct->ct_bus_reset = bshw_bus_reset; 269 ct->ct_synch_setup = bshw_synch_setup; 270 271 ct->sc_xmode = CT_XMODE_DMA; 272 if (chp->ch_memh != NULL) 273 ct->sc_xmode |= CT_XMODE_PIO; 274 275 ct->sc_chiprev = chiprev; 276 switch (chiprev) 277 { 278 case CT_WD33C93: 279 /* s = "WD33C93"; */ 280 ct->sc_chipclk = 8; 281 break; 282 case CT_WD33C93_A: 283 if (DVCFG_MAJOR(device_get_flags(dev)) > 0) 284 { 285 /* s = "AM33C93_A"; */ 286 ct->sc_chipclk = 20; 287 ct->sc_chiprev = CT_AM33C93_A; 288 } 289 else 290 { 291 /* s = "WD33C93_A"; */ 292 ct->sc_chipclk = 10; 293 } 294 break; 295 296 case CT_AM33C93_A: 297 /* s = "AM33C93_A"; */ 298 ct->sc_chipclk = 20; 299 break; 300 301 default: 302 case CT_WD33C93_B: 303 /* s = "WD33C93_B"; */ 304 ct->sc_chipclk = 20; 305 break; 306 } 307#if 0 308 printf("%s: chiprev %s chipclk %d Mhz\n", 309 slp->sl_dev.dv_xname, s, ct->sc_chipclk); 310#endif 311 312 slp->sl_dev = dev; 313 slp->sl_hostid = bs->sc_hostid; 314 slp->sl_irq = isa_get_irq(dev); 315 slp->sl_cfgflags = device_get_flags(dev); 316 317 s = splcam(); 318 ctattachsubr(ct); 319 splx(s); 320 321 if (bus_setup_intr(dev, ct->irq_res, INTR_TYPE_CAM, 322 (driver_intr_t *)ctintr, ct, &ct->sc_ih)) { 323 ct_space_unmap(dev, ct); 324 return ENXIO; 325 } 326 327 return 0; 328} 329 330static struct bshw * 331ct_find_hw(device_t dev) 332{ 333 return DVCFG_HW(&bshw_hwsel, DVCFG_MAJOR(device_get_flags(dev))); 334} 335 336static int 337ct_space_map(device_t dev, struct bshw *hw, 338 struct resource **iohp, struct resource **memhp) 339{ 340 int port_rid, mem_rid; 341 342 *memhp = NULL; 343 344 port_rid = 0; 345 *iohp = bus_alloc_resource(dev, SYS_RES_IOPORT, &port_rid, 0, ~0, 346 BSHW_IOSZ, RF_ACTIVE); 347 if (*iohp == NULL) 348 return ENXIO; 349 350 if ((hw->hw_flags & BSHW_SMFIFO) == 0 || isa_get_maddr(dev) == -1) 351 return 0; 352 353 mem_rid = 0; 354 *memhp = bus_alloc_resource(dev, SYS_RES_MEMORY, &mem_rid, 0, ~0, 355 BSHW_MEMSZ, RF_ACTIVE); 356 if (*memhp == NULL) { 357 bus_release_resource(dev, SYS_RES_IOPORT, port_rid, *iohp); 358 return ENXIO; 359 } 360 361 return 0; 362} 363 364static void 365ct_space_unmap(device_t dev, struct ct_softc *ct) 366{ 367 if (ct->port_res != NULL) 368 bus_release_resource(dev, SYS_RES_IOPORT, 0, ct->port_res); 369 if (ct->mem_res != NULL) 370 bus_release_resource(dev, SYS_RES_MEMORY, 0, ct->mem_res); 371 if (ct->irq_res != NULL) 372 bus_release_resource(dev, SYS_RES_IRQ, 0, ct->irq_res); 373 if (ct->drq_res != NULL) 374 bus_release_resource(dev, SYS_RES_DRQ, 0, ct->drq_res); 375} 376 377static void 378ct_dmamap(void *arg, bus_dma_segment_t *seg, int nseg, int error) 379{ 380 bus_addr_t *addr = (bus_addr_t *)arg; 381 382 *addr = seg->ds_addr; 383} 384 385static void 386ct_isa_bus_access_weight(chp) 387 struct ct_bus_access_handle *chp; 388{ 389 390 outb(0x5f, 0); 391} 392 393static void 394ct_isa_dmasync_before(ct) 395 struct ct_softc *ct; 396{ 397 398 if (need_pre_dma_flush) 399 wbinvd(); 400} 401 402static void 403ct_isa_dmasync_after(ct) 404 struct ct_softc *ct; 405{ 406 407 if (need_post_dma_flush) 408 invd(); 409} 410