bshw_machdep.c revision 79697
1/* $FreeBSD: head/sys/dev/ct/bshw_machdep.c 79697 2001-07-14 00:38:51Z non $ */ 2/* $NecBSD: bshw_machdep.c,v 1.8.12.6 2001/06/29 06:28:05 honda Exp $ */ 3/* $NetBSD$ */ 4 5/* 6 * [NetBSD for NEC PC-98 series] 7 * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 8 * NetBSD/pc98 porting staff. All rights reserved. 9 * 10 * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 11 * Naofumi HONDA. All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. The name of the author may not be used to endorse or promote products 22 * derived from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 28 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 32 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 33 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37#include "opt_ddb.h" 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> 42#if defined(__FreeBSD__) && __FreeBSD_version > 500001 43#include <sys/bio.h> 44#endif /* __ FreeBSD__ */ 45#include <sys/buf.h> 46#include <sys/queue.h> 47#include <sys/malloc.h> 48#include <sys/errno.h> 49 50#include <vm/vm.h> 51 52#ifdef __NetBSD__ 53#include <sys/device.h> 54 55#include <machine/bus.h> 56#include <machine/intr.h> 57 58#include <dev/scsipi/scsi_all.h> 59#include <dev/scsipi/scsipi_all.h> 60#include <dev/scsipi/scsiconf.h> 61#include <dev/scsipi/scsi_disk.h> 62 63#include <machine/dvcfg.h> 64#include <machine/physio_proc.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/ct_machdep.h> 71#include <i386/Cbus/dev/ct/bshwvar.h> 72#endif /* __NetBSD__ */ 73 74#ifdef __FreeBSD__ 75#include <machine/bus.h> 76#include <machine/clock.h> 77#include <machine/md_var.h> 78 79#include <machine/dvcfg.h> 80#include <machine/physio_proc.h> 81 82#include <cam/scsi/scsi_low.h> 83 84#include <dev/ic/wd33c93reg.h> 85#include <dev/ct/ctvar.h> 86#include <dev/ct/ct_machdep.h> 87#include <dev/ct/bshwvar.h> 88 89#include <vm/pmap.h> 90#endif /* __FreeBSD__ */ 91 92#define BSHW_IO_CONTROL_FLAGS 0 93 94u_int bshw_io_control = BSHW_IO_CONTROL_FLAGS; 95int bshw_data_read_bytes = 4096; 96int bshw_data_write_bytes = 4096; 97 98/********************************************************* 99 * OS dep part 100 *********************************************************/ 101#ifdef __NetBSD__ 102#define BSHW_PAGE_SIZE NBPG 103#endif /* __NetBSD__ */ 104 105#ifdef __FreeBSD__ 106#define BSHW_PAGE_SIZE PAGE_SIZE 107typedef unsigned long vaddr_t; 108#endif /* __FreeBSD__ */ 109 110/********************************************************* 111 * GENERIC MACHDEP FUNCTIONS 112 *********************************************************/ 113void 114bshw_synch_setup(ct, ti) 115 struct ct_softc *ct; 116 struct targ_info *ti; 117{ 118 struct ct_bus_access_handle *chp = &ct->sc_ch; 119 struct ct_targ_info *cti = (void *) ti; 120 struct bshw_softc *bs = ct->ct_hw; 121 struct bshw *hw = bs->sc_hw; 122 123 if (hw->hw_sregaddr == 0) 124 return; 125 126 ct_cr_write_1(chp, hw->hw_sregaddr + ti->ti_id, cti->cti_syncreg); 127 if (hw->hw_flags & BSHW_DOUBLE_DMACHAN) 128 { 129 ct_cr_write_1(chp, hw->hw_sregaddr + ti->ti_id + 8, 130 cti->cti_syncreg); 131 } 132} 133 134void 135bshw_bus_reset(ct) 136 struct ct_softc *ct; 137{ 138 struct scsi_low_softc *slp = &ct->sc_sclow; 139 struct ct_bus_access_handle *chp = &ct->sc_ch; 140 struct bshw_softc *bs = ct->ct_hw; 141 struct bshw *hw = bs->sc_hw; 142 bus_addr_t offs; 143 u_int8_t regv; 144 int i; 145 146 /* open hardware busmaster mode */ 147 if (hw->hw_dma_init != NULL && ((*hw->hw_dma_init)(ct)) != 0) 148 { 149 printf("%s: change mode using external DMA (%x)\n", 150 slp->sl_xname, (u_int)ct_cr_read_1(chp, 0x37)); 151 } 152 153 /* clear hardware synch registers */ 154 offs = hw->hw_sregaddr; 155 if (offs != 0) 156 { 157 for (i = 0; i < 8; i ++, offs ++) 158 { 159 ct_cr_write_1(chp, offs, 0); 160 if ((hw->hw_flags & BSHW_DOUBLE_DMACHAN) != 0) 161 ct_cr_write_1(chp, offs + 8, 0); 162 } 163 } 164 165 /* disable interrupt & assert reset */ 166 regv = ct_cr_read_1(chp, wd3s_mbank); 167 regv |= MBR_RST; 168 regv &= ~MBR_IEN; 169 ct_cr_write_1(chp, wd3s_mbank, regv); 170 171 SCSI_LOW_DELAY(500000); 172 173 /* reset signal off */ 174 regv &= ~MBR_RST; 175 ct_cr_write_1(chp, wd3s_mbank, regv); 176 177 /* interrupt enable */ 178 regv |= MBR_IEN; 179 ct_cr_write_1(chp, wd3s_mbank, regv); 180} 181 182/* probe */ 183int 184bshw_read_settings(chp, bs) 185 struct ct_bus_access_handle *chp; 186 struct bshw_softc *bs; 187{ 188 static int irq_tbl[] = { 3, 5, 6, 9, 12, 13 }; 189 190 bs->sc_hostid = (ct_cr_read_1(chp, wd3s_auxc) & AUXCR_HIDM); 191 bs->sc_irq = irq_tbl[(ct_cr_read_1(chp, wd3s_auxc) >> 3) & 7]; 192 bs->sc_drq = ct_cmdp_read_1(chp) & 3; 193 return 0; 194} 195 196/********************************************************* 197 * DMA PIO TRANSFER (SMIT) 198 *********************************************************/ 199#define LC_SMIT_TIMEOUT 2 /* 2 sec: timeout for a fifo status ready */ 200#define LC_SMIT_OFFSET 0x1000 201#define LC_FSZ DEV_BSIZE 202#define LC_SFSZ 0x0c 203#define LC_REST (LC_FSZ - LC_SFSZ) 204 205#define BSHW_LC_FSET 0x36 206#define BSHW_LC_FCTRL 0x44 207#define FCTRL_EN 0x01 208#define FCTRL_WRITE 0x02 209 210#define SF_ABORT 0x08 211#define SF_RDY 0x10 212 213static __inline void bshw_lc_smit_start __P((struct ct_softc *, int, u_int)); 214static __inline void bshw_lc_smit_stop __P((struct ct_softc *)); 215static int bshw_lc_smit_fstat __P((struct ct_softc *, int, int)); 216 217static __inline void 218bshw_lc_smit_stop(ct) 219 struct ct_softc *ct; 220{ 221 struct ct_bus_access_handle *chp = &ct->sc_ch; 222 223 ct_cr_write_1(chp, BSHW_LC_FCTRL, 0); 224 ct_cmdp_write_1(chp, CMDP_DMER); 225} 226 227static __inline void 228bshw_lc_smit_start(ct, count, direction) 229 struct ct_softc *ct; 230 int count; 231 u_int direction; 232{ 233 struct ct_bus_access_handle *chp = &ct->sc_ch; 234 u_int8_t pval, val; 235 236 val = ct_cr_read_1(chp, BSHW_LC_FSET); 237 cthw_set_count(chp, count); 238 239 pval = FCTRL_EN; 240 if (direction == SCSI_LOW_WRITE) 241 pval |= (val & 0xe0) | FCTRL_WRITE; 242 ct_cr_write_1(chp, BSHW_LC_FCTRL, pval); 243 ct_cr_write_1(chp, wd3s_cmd, WD3S_TFR_INFO); 244} 245 246static int 247bshw_lc_smit_fstat(ct, wc, read) 248 struct ct_softc *ct; 249 int wc, read; 250{ 251 struct ct_bus_access_handle *chp = &ct->sc_ch; 252 u_int8_t stat; 253 254 while (wc -- > 0) 255 { 256 chp->ch_bus_weight(chp); 257 stat = ct_cmdp_read_1(chp); 258 if (read == SCSI_LOW_READ) 259 { 260 if ((stat & SF_RDY) != 0) 261 return 0; 262 if ((stat & SF_ABORT) != 0) 263 return EIO; 264 } 265 else 266 { 267 if ((stat & SF_ABORT) != 0) 268 return EIO; 269 if ((stat & SF_RDY) != 0) 270 return 0; 271 } 272 } 273 274 printf("%s: SMIT fifo status timeout\n", ct->sc_sclow.sl_xname); 275 return EIO; 276} 277 278void 279bshw_smit_xfer_stop(ct) 280 struct ct_softc *ct; 281{ 282 struct scsi_low_softc *slp = &ct->sc_sclow; 283 struct bshw_softc *bs = ct->ct_hw; 284 struct targ_info *ti; 285 struct sc_p *sp = &slp->sl_scp; 286 u_int count; 287 288 bshw_lc_smit_stop(ct); 289 290 ti = slp->sl_Tnexus; 291 if (ti == NULL) 292 return; 293 294 if (ti->ti_phase == PH_DATA) 295 { 296 count = cthw_get_count(&ct->sc_ch); 297 if (count < bs->sc_sdatalen) 298 { 299 if (sp->scp_direction == SCSI_LOW_READ && 300 count != bs->sc_edatalen) 301 goto bad; 302 303 count = bs->sc_sdatalen - count; 304 if (count > (u_int) sp->scp_datalen) 305 goto bad; 306 307 sp->scp_data += count; 308 sp->scp_datalen -= count; 309 } 310 else if (count > bs->sc_sdatalen) 311 { 312bad: 313 printf("%s: smit_xfer_end: cnt error\n", slp->sl_xname); 314 slp->sl_error |= PDMAERR; 315 } 316 scsi_low_data_finish(slp); 317 } 318 else 319 { 320 printf("%s: smit_xfer_end: phase miss\n", slp->sl_xname); 321 slp->sl_error |= PDMAERR; 322 } 323} 324 325int 326bshw_smit_xfer_start(ct) 327 struct ct_softc *ct; 328{ 329 struct scsi_low_softc *slp = &ct->sc_sclow; 330 struct ct_bus_access_handle *chp = &ct->sc_ch; 331 struct bshw_softc *bs = ct->ct_hw; 332 struct sc_p *sp = &slp->sl_scp; 333 struct targ_info *ti = slp->sl_Tnexus; 334 struct ct_targ_info *cti = (void *) ti; 335 u_int datalen, count, io_control; 336 int wc; 337 u_int8_t *data; 338 339 io_control = bs->sc_io_control | bshw_io_control; 340 if ((io_control & BSHW_SMIT_BLOCK) != 0) 341 return EINVAL; 342 343 if ((slp->sl_scp.scp_datalen % DEV_BSIZE) != 0) 344 return EINVAL; 345 346 datalen = sp->scp_datalen; 347 if (slp->sl_scp.scp_direction == SCSI_LOW_READ) 348 { 349 if ((io_control & BSHW_READ_INTERRUPT_DRIVEN) != 0 && 350 datalen > bshw_data_read_bytes) 351 datalen = bshw_data_read_bytes; 352 } 353 else 354 { 355 if ((io_control & BSHW_WRITE_INTERRUPT_DRIVEN) != 0 && 356 datalen > bshw_data_write_bytes) 357 datalen = bshw_data_write_bytes; 358 } 359 360 bs->sc_sdatalen = datalen; 361 data = sp->scp_data; 362 wc = LC_SMIT_TIMEOUT * 1024 * 1024; 363 364 ct_cr_write_1(chp, wd3s_ctrl, ct->sc_creg | CR_DMA); 365 bshw_lc_smit_start(ct, datalen, sp->scp_direction); 366 367 if (sp->scp_direction == SCSI_LOW_READ) 368 { 369 do 370 { 371 if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_READ)) 372 break; 373 374 count = (datalen > LC_FSZ ? LC_FSZ : datalen); 375 bus_space_read_region_4(chp->ch_memt, chp->ch_memh, 376 LC_SMIT_OFFSET, (u_int32_t *) data, count >> 2); 377 data += count; 378 datalen -= count; 379 } 380 while (datalen > 0); 381 382 bs->sc_edatalen = datalen; 383 } 384 else 385 { 386 do 387 { 388 if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE)) 389 break; 390 if (cti->cti_syncreg == 0) 391 { 392 /* XXX: 393 * If async transfer, reconfirm a scsi phase 394 * again. Unless C bus might hang up. 395 */ 396 if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE)) 397 break; 398 } 399 400 count = (datalen > LC_SFSZ ? LC_SFSZ : datalen); 401 bus_space_write_region_4(chp->ch_memt, chp->ch_memh, 402 LC_SMIT_OFFSET, (u_int32_t *) data, count >> 2); 403 data += count; 404 datalen -= count; 405 406 if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE)) 407 break; 408 409 count = (datalen > LC_REST ? LC_REST : datalen); 410 bus_space_write_region_4(chp->ch_memt, chp->ch_memh, 411 LC_SMIT_OFFSET + LC_SFSZ, 412 (u_int32_t *) data, count >> 2); 413 data += count; 414 datalen -= count; 415 } 416 while (datalen > 0); 417 } 418 return 0; 419} 420 421/********************************************************* 422 * DMA TRANSFER (BS) 423 *********************************************************/ 424static __inline void bshw_dma_write_1 \ 425 __P((struct ct_bus_access_handle *, bus_addr_t, u_int8_t)); 426static void bshw_dmastart __P((struct ct_softc *)); 427static void bshw_dmadone __P((struct ct_softc *)); 428 429int 430bshw_dma_xfer_start(ct) 431 struct ct_softc *ct; 432{ 433 struct scsi_low_softc *slp = &ct->sc_sclow; 434 struct sc_p *sp = &slp->sl_scp; 435 struct ct_bus_access_handle *chp = &ct->sc_ch; 436 struct bshw_softc *bs = ct->ct_hw; 437 vaddr_t va, endva, phys, nphys; 438 u_int io_control; 439 440 io_control = bs->sc_io_control | bshw_io_control; 441 if ((io_control & BSHW_DMA_BLOCK) != 0 && sp->scp_datalen < 256) 442 return EINVAL; 443 444 ct_cr_write_1(chp, wd3s_ctrl, ct->sc_creg | CR_DMA); 445 phys = vtophys((vaddr_t) sp->scp_data); 446 if (phys >= bs->sc_minphys) 447 { 448 /* setup segaddr */ 449 bs->sc_segaddr = bs->sc_bounce_phys; 450 /* setup seglen */ 451 bs->sc_seglen = sp->scp_datalen; 452 if (bs->sc_seglen > bs->sc_bounce_size) 453 bs->sc_seglen = bs->sc_bounce_size; 454 /* setup bufp */ 455 bs->sc_bufp = bs->sc_bounce_addr; 456 if (sp->scp_direction == SCSI_LOW_WRITE) 457 bcopy(sp->scp_data, bs->sc_bufp, bs->sc_seglen); 458 } 459 else 460 { 461 /* setup segaddr */ 462 bs->sc_segaddr = (u_int8_t *) phys; 463 /* setup seglen */ 464 endva = (vaddr_t) round_page((vaddr_t) sp->scp_data + sp->scp_datalen); 465 for (va = (vaddr_t) sp->scp_data; ; phys = nphys) 466 { 467 if ((va += BSHW_PAGE_SIZE) >= endva) 468 { 469 bs->sc_seglen = sp->scp_datalen; 470 break; 471 } 472 473 nphys = vtophys(va); 474 if (phys + BSHW_PAGE_SIZE != nphys || nphys >= bs->sc_minphys) 475 { 476 bs->sc_seglen = 477 (u_int8_t *) trunc_page(va) - sp->scp_data; 478 break; 479 } 480 } 481 /* setup bufp */ 482 bs->sc_bufp = NULL; 483 } 484 485 bshw_dmastart(ct); 486 cthw_set_count(chp, bs->sc_seglen); 487 ct_cr_write_1(chp, wd3s_cmd, WD3S_TFR_INFO); 488 return 0; 489} 490 491void 492bshw_dma_xfer_stop(ct) 493 struct ct_softc *ct; 494{ 495 struct scsi_low_softc *slp = &ct->sc_sclow; 496 struct sc_p *sp = &slp->sl_scp; 497 struct bshw_softc *bs = ct->ct_hw; 498 struct targ_info *ti; 499 u_int count, transbytes; 500 501 bshw_dmadone(ct); 502 503 ti = slp->sl_Tnexus; 504 if (ti == NULL) 505 return; 506 507 if (ti->ti_phase == PH_DATA) 508 { 509 count = cthw_get_count(&ct->sc_ch); 510 if (count < (u_int) bs->sc_seglen) 511 { 512 transbytes = bs->sc_seglen - count; 513 if (bs->sc_bufp != NULL && 514 sp->scp_direction == SCSI_LOW_READ) 515 bcopy(bs->sc_bufp, sp->scp_data, transbytes); 516 517 sp->scp_data += transbytes; 518 sp->scp_datalen -= transbytes; 519 } 520 else if (count > (u_int) bs->sc_seglen) 521 { 522 printf("%s: port data %x != seglen %x\n", 523 slp->sl_xname, count, bs->sc_seglen); 524 slp->sl_error |= PDMAERR; 525 } 526 527 scsi_low_data_finish(slp); 528 } 529 else 530 { 531 printf("%s: extra DMA interrupt\n", slp->sl_xname); 532 slp->sl_error |= PDMAERR; 533 } 534 535 bs->sc_bufp = NULL; 536} 537 538/* common dma settings */ 539#undef DMA1_SMSK 540#define DMA1_SMSK (0x15) 541#undef DMA1_MODE 542#define DMA1_MODE (0x17) 543#undef DMA1_FFC 544#define DMA1_FFC (0x19) 545#undef DMA1_CHN 546#define DMA1_CHN(c) (0x01 + ((c) << 2)) 547 548#define DMA37SM_SET 0x04 549#define DMA37MD_WRITE 0x04 550#define DMA37MD_READ 0x08 551#define DMA37MD_SINGLE 0x40 552 553static bus_addr_t dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 }; 554 555static __inline void 556bshw_dma_write_1(chp, port, val) 557 struct ct_bus_access_handle *chp; 558 bus_addr_t port; 559 u_int8_t val; 560{ 561 562 CT_BUS_WEIGHT(chp); 563 outb(port, val); 564} 565 566static void 567bshw_dmastart(ct) 568 struct ct_softc *ct; 569{ 570 struct scsi_low_softc *slp = &ct->sc_sclow; 571 struct bshw_softc *bs = ct->ct_hw; 572 struct ct_bus_access_handle *chp = &ct->sc_ch; 573 int chan = bs->sc_drq; 574 bus_addr_t waport; 575 u_int8_t regv, *phys = bs->sc_segaddr; 576 u_int nbytes = bs->sc_seglen; 577 578 /* flush cpu cache */ 579 (*bs->sc_dmasync_before) (ct); 580 581 /* 582 * Program one of DMA channels 0..3. These are 583 * byte mode channels. 584 */ 585 /* set dma channel mode, and reset address ff */ 586 587 if (slp->sl_scp.scp_direction == SCSI_LOW_READ) 588 regv = DMA37MD_WRITE | DMA37MD_SINGLE | chan; 589 else 590 regv = DMA37MD_READ | DMA37MD_SINGLE | chan; 591 592 bshw_dma_write_1(chp, DMA1_MODE, regv); 593 bshw_dma_write_1(chp, DMA1_FFC, 0); 594 595 /* send start address */ 596 waport = DMA1_CHN(chan); 597 bshw_dma_write_1(chp, waport, (u_int) phys); 598 bshw_dma_write_1(chp, waport, ((u_int) phys) >> 8); 599 bshw_dma_write_1(chp, dmapageport[chan], ((u_int) phys) >> 16); 600 601 /* send count */ 602 bshw_dma_write_1(chp, waport + 2, --nbytes); 603 bshw_dma_write_1(chp, waport + 2, nbytes >> 8); 604 605 /* vendor unique hook */ 606 if (bs->sc_hw->hw_dma_start) 607 (*bs->sc_hw->hw_dma_start)(ct); 608 609 bshw_dma_write_1(chp, DMA1_SMSK, chan); 610 ct_cmdp_write_1(chp, CMDP_DMES); 611} 612 613static void 614bshw_dmadone(ct) 615 struct ct_softc *ct; 616{ 617 struct bshw_softc *bs = ct->ct_hw; 618 struct ct_bus_access_handle *chp = &ct->sc_ch; 619 620 bshw_dma_write_1(chp, DMA1_SMSK, (bs->sc_drq | DMA37SM_SET)); 621 ct_cmdp_write_1(chp, CMDP_DMER); 622 623 /* vendor unique hook */ 624 if (bs->sc_hw->hw_dma_stop) 625 (*bs->sc_hw->hw_dma_stop) (ct); 626 627 /* flush cpu cache */ 628 (*bs->sc_dmasync_after) (ct); 629} 630 631/********************************************** 632 * VENDOR UNIQUE DMA FUNCS 633 **********************************************/ 634static int bshw_dma_init_sc98 __P((struct ct_softc *)); 635static void bshw_dma_start_sc98 __P((struct ct_softc *)); 636static void bshw_dma_stop_sc98 __P((struct ct_softc *)); 637static int bshw_dma_init_texa __P((struct ct_softc *)); 638static void bshw_dma_start_elecom __P((struct ct_softc *)); 639static void bshw_dma_stop_elecom __P((struct ct_softc *)); 640 641static int 642bshw_dma_init_texa(ct) 643 struct ct_softc *ct; 644{ 645 struct ct_bus_access_handle *chp = &ct->sc_ch; 646 u_int8_t regval; 647 648 if ((regval = ct_cr_read_1(chp, 0x37)) & 0x08) 649 return 0; 650 651 ct_cr_write_1(chp, 0x37, regval | 0x08); 652 regval = ct_cr_read_1(chp, 0x3f); 653 ct_cr_write_1(chp, 0x3f, regval | 0x08); 654 return 1; 655} 656 657static int 658bshw_dma_init_sc98(ct) 659 struct ct_softc *ct; 660{ 661 struct ct_bus_access_handle *chp = &ct->sc_ch; 662 663 if (ct_cr_read_1(chp, 0x37) & 0x08) 664 return 0; 665 666 /* If your card is SC98 with bios ver 1.01 or 1.02 under no PCI */ 667 ct_cr_write_1(chp, 0x37, 0x1a); 668 ct_cr_write_1(chp, 0x3f, 0x1a); 669#if 0 670 /* only valid for IO */ 671 ct_cr_write_1(chp, 0x40, 0xf4); 672 ct_cr_write_1(chp, 0x41, 0x9); 673 ct_cr_write_1(chp, 0x43, 0xff); 674 ct_cr_write_1(chp, 0x46, 0x4e); 675 676 ct_cr_write_1(chp, 0x48, 0xf4); 677 ct_cr_write_1(chp, 0x49, 0x9); 678 ct_cr_write_1(chp, 0x4b, 0xff); 679 ct_cr_write_1(chp, 0x4e, 0x4e); 680#endif 681 return 1; 682} 683 684static void 685bshw_dma_start_sc98(ct) 686 struct ct_softc *ct; 687{ 688 struct ct_bus_access_handle *chp = &ct->sc_ch; 689 690 ct_cr_write_1(chp, 0x73, 0x32); 691 ct_cr_write_1(chp, 0x74, 0x23); 692} 693 694static void 695bshw_dma_stop_sc98(ct) 696 struct ct_softc *ct; 697{ 698 struct ct_bus_access_handle *chp = &ct->sc_ch; 699 700 ct_cr_write_1(chp, 0x73, 0x43); 701 ct_cr_write_1(chp, 0x74, 0x34); 702} 703 704static void 705bshw_dma_start_elecom(ct) 706 struct ct_softc *ct; 707{ 708 struct ct_bus_access_handle *chp = &ct->sc_ch; 709 u_int8_t tmp = ct_cr_read_1(chp, 0x4c); 710 711 ct_cr_write_1(chp, 0x32, tmp & 0xdf); 712} 713 714static void 715bshw_dma_stop_elecom(ct) 716 struct ct_softc *ct; 717{ 718 struct ct_bus_access_handle *chp = &ct->sc_ch; 719 u_int8_t tmp = ct_cr_read_1(chp, 0x4c); 720 721 ct_cr_write_1(chp, 0x32, tmp | 0x20); 722} 723 724static struct bshw bshw_generic = { 725 BSHW_SYNC_RELOAD, 726 727 0, 728 729 NULL, 730 NULL, 731 NULL, 732}; 733 734static struct bshw bshw_sc98 = { 735 BSHW_DOUBLE_DMACHAN, 736 737 0x60, 738 739 bshw_dma_init_sc98, 740 bshw_dma_start_sc98, 741 bshw_dma_stop_sc98, 742}; 743 744static struct bshw bshw_texa = { 745 BSHW_DOUBLE_DMACHAN, 746 747 0x60, 748 749 bshw_dma_init_texa, 750 NULL, 751 NULL, 752}; 753 754static struct bshw bshw_elecom = { 755 0, 756 757 0x38, 758 759 NULL, 760 bshw_dma_start_elecom, 761 bshw_dma_stop_elecom, 762}; 763 764static struct bshw bshw_lc_smit = { 765 BSHW_SMFIFO | BSHW_DOUBLE_DMACHAN, 766 767 0x60, 768 769 NULL, 770 NULL, 771 NULL, 772}; 773 774static struct bshw bshw_lha20X = { 775 BSHW_DOUBLE_DMACHAN, 776 777 0x60, 778 779 NULL, 780 NULL, 781 NULL, 782}; 783 784/* hw tabs */ 785static dvcfg_hw_t bshw_hwsel_array[] = { 786/* 0x00 */ &bshw_generic, 787/* 0x01 */ &bshw_sc98, 788/* 0x02 */ &bshw_texa, 789/* 0x03 */ &bshw_elecom, 790/* 0x04 */ &bshw_lc_smit, 791/* 0x05 */ &bshw_lha20X, 792}; 793 794struct dvcfg_hwsel bshw_hwsel = { 795 DVCFG_HWSEL_SZ(bshw_hwsel_array), 796 bshw_hwsel_array 797}; 798