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