1 /* $NecBSD: bshw_machdep.c,v 1.8.12.6 2001/06/29 06:28:05 honda Exp $ */
8 * [NetBSD for NEC PC-98 series]
9 * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
10 * NetBSD/pc98 porting staff. All rights reserved.
12 * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
13 * Naofumi HONDA. All rights reserved.
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. The name of the author may not be used to endorse or promote products
24 * derived from this software without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
30 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
46 #include <sys/queue.h>
47 #include <sys/malloc.h>
48 #include <sys/errno.h>
53 #include <machine/bus.h>
54 #include <machine/md_var.h>
56 #include <compat/netbsd/dvcfg.h>
58 #include <cam/scsi/scsi_low.h>
60 #include <dev/ic/wd33c93reg.h>
61 #include <dev/ct/ctvar.h>
62 #include <dev/ct/ct_machdep.h>
63 #include <dev/ct/bshwvar.h>
67 #define BSHW_IO_CONTROL_FLAGS 0
69 u_int bshw_io_control = BSHW_IO_CONTROL_FLAGS;
70 int bshw_data_read_bytes = 4096;
71 int bshw_data_write_bytes = 4096;
73 /*********************************************************
75 *********************************************************/
76 typedef unsigned long vaddr_t;
78 /*********************************************************
79 * GENERIC MACHDEP FUNCTIONS
80 *********************************************************/
82 bshw_synch_setup(struct ct_softc *ct, struct targ_info *ti)
84 struct ct_bus_access_handle *chp = &ct->sc_ch;
85 struct ct_targ_info *cti = (void *) ti;
86 struct bshw_softc *bs = ct->ct_hw;
87 struct bshw *hw = bs->sc_hw;
89 if (hw->hw_sregaddr == 0)
92 ct_cr_write_1(chp, hw->hw_sregaddr + ti->ti_id, cti->cti_syncreg);
93 if (hw->hw_flags & BSHW_DOUBLE_DMACHAN)
95 ct_cr_write_1(chp, hw->hw_sregaddr + ti->ti_id + 8,
101 bshw_bus_reset(struct ct_softc *ct)
103 struct scsi_low_softc *slp = &ct->sc_sclow;
104 struct ct_bus_access_handle *chp = &ct->sc_ch;
105 struct bshw_softc *bs = ct->ct_hw;
106 struct bshw *hw = bs->sc_hw;
111 /* open hardware busmaster mode */
112 if (hw->hw_dma_init != NULL && ((*hw->hw_dma_init)(ct)) != 0)
114 device_printf(slp->sl_dev,
115 "change mode using external DMA (%x)\n",
116 (u_int)ct_cr_read_1(chp, 0x37));
119 /* clear hardware synch registers */
120 offs = hw->hw_sregaddr;
123 for (i = 0; i < 8; i ++, offs ++)
125 ct_cr_write_1(chp, offs, 0);
126 if ((hw->hw_flags & BSHW_DOUBLE_DMACHAN) != 0)
127 ct_cr_write_1(chp, offs + 8, 0);
131 /* disable interrupt & assert reset */
132 regv = ct_cr_read_1(chp, wd3s_mbank);
135 ct_cr_write_1(chp, wd3s_mbank, regv);
139 /* reset signal off */
141 ct_cr_write_1(chp, wd3s_mbank, regv);
143 /* interrupt enable */
145 ct_cr_write_1(chp, wd3s_mbank, regv);
150 bshw_read_settings(struct ct_bus_access_handle *chp, struct bshw_softc *bs)
152 static int irq_tbl[] = { 3, 5, 6, 9, 12, 13 };
154 bs->sc_hostid = (ct_cr_read_1(chp, wd3s_auxc) & AUXCR_HIDM);
155 bs->sc_irq = irq_tbl[(ct_cr_read_1(chp, wd3s_auxc) >> 3) & 7];
156 bs->sc_drq = ct_cmdp_read_1(chp) & 3;
160 /*********************************************************
161 * DMA PIO TRANSFER (SMIT)
162 *********************************************************/
163 #define LC_SMIT_TIMEOUT 2 /* 2 sec: timeout for a fifo status ready */
164 #define LC_SMIT_OFFSET 0x1000
165 #define LC_FSZ DEV_BSIZE
167 #define LC_REST (LC_FSZ - LC_SFSZ)
169 #define BSHW_LC_FSET 0x36
170 #define BSHW_LC_FCTRL 0x44
171 #define FCTRL_EN 0x01
172 #define FCTRL_WRITE 0x02
174 #define SF_ABORT 0x08
177 static __inline void bshw_lc_smit_start(struct ct_softc *, int, u_int);
178 static __inline void bshw_lc_smit_stop(struct ct_softc *);
179 static int bshw_lc_smit_fstat(struct ct_softc *, int, int);
182 bshw_lc_smit_stop(struct ct_softc *ct)
184 struct ct_bus_access_handle *chp = &ct->sc_ch;
186 ct_cr_write_1(chp, BSHW_LC_FCTRL, 0);
187 ct_cmdp_write_1(chp, CMDP_DMER);
191 bshw_lc_smit_start(struct ct_softc *ct, int count, u_int direction)
193 struct ct_bus_access_handle *chp = &ct->sc_ch;
196 val = ct_cr_read_1(chp, BSHW_LC_FSET);
197 cthw_set_count(chp, count);
200 if (direction == SCSI_LOW_WRITE)
201 pval |= (val & 0xe0) | FCTRL_WRITE;
202 ct_cr_write_1(chp, BSHW_LC_FCTRL, pval);
203 ct_cr_write_1(chp, wd3s_cmd, WD3S_TFR_INFO);
207 bshw_lc_smit_fstat(struct ct_softc *ct, int wc, int read)
209 struct ct_bus_access_handle *chp = &ct->sc_ch;
214 chp->ch_bus_weight(chp);
215 stat = ct_cmdp_read_1(chp);
216 if (read == SCSI_LOW_READ)
218 if ((stat & SF_RDY) != 0)
220 if ((stat & SF_ABORT) != 0)
225 if ((stat & SF_ABORT) != 0)
227 if ((stat & SF_RDY) != 0)
232 device_printf(ct->sc_sclow.sl_dev, "SMIT fifo status timeout\n");
237 bshw_smit_xfer_stop(struct ct_softc *ct)
239 struct scsi_low_softc *slp = &ct->sc_sclow;
240 struct bshw_softc *bs = ct->ct_hw;
241 struct targ_info *ti;
242 struct sc_p *sp = &slp->sl_scp;
245 bshw_lc_smit_stop(ct);
251 if (ti->ti_phase == PH_DATA)
253 count = cthw_get_count(&ct->sc_ch);
254 if (count < bs->sc_sdatalen)
256 if (sp->scp_direction == SCSI_LOW_READ &&
257 count != bs->sc_edatalen)
260 count = bs->sc_sdatalen - count;
261 if (count > (u_int) sp->scp_datalen)
264 sp->scp_data += count;
265 sp->scp_datalen -= count;
267 else if (count > bs->sc_sdatalen)
270 device_printf(slp->sl_dev,
271 "smit_xfer_end: cnt error\n");
272 slp->sl_error |= PDMAERR;
274 scsi_low_data_finish(slp);
278 device_printf(slp->sl_dev, "smit_xfer_end: phase miss\n");
279 slp->sl_error |= PDMAERR;
284 bshw_smit_xfer_start(struct ct_softc *ct)
286 struct scsi_low_softc *slp = &ct->sc_sclow;
287 struct ct_bus_access_handle *chp = &ct->sc_ch;
288 struct bshw_softc *bs = ct->ct_hw;
289 struct sc_p *sp = &slp->sl_scp;
290 struct targ_info *ti = slp->sl_Tnexus;
291 struct ct_targ_info *cti = (void *) ti;
292 u_int datalen, count, io_control;
296 io_control = bs->sc_io_control | bshw_io_control;
297 if ((io_control & BSHW_SMIT_BLOCK) != 0)
300 if ((slp->sl_scp.scp_datalen % DEV_BSIZE) != 0)
303 datalen = sp->scp_datalen;
304 if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
306 if ((io_control & BSHW_READ_INTERRUPT_DRIVEN) != 0 &&
307 datalen > bshw_data_read_bytes)
308 datalen = bshw_data_read_bytes;
312 if ((io_control & BSHW_WRITE_INTERRUPT_DRIVEN) != 0 &&
313 datalen > bshw_data_write_bytes)
314 datalen = bshw_data_write_bytes;
317 bs->sc_sdatalen = datalen;
319 wc = LC_SMIT_TIMEOUT * 1024 * 1024;
321 ct_cr_write_1(chp, wd3s_ctrl, ct->sc_creg | CR_DMA);
322 bshw_lc_smit_start(ct, datalen, sp->scp_direction);
324 if (sp->scp_direction == SCSI_LOW_READ)
328 if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_READ))
331 count = (datalen > LC_FSZ ? LC_FSZ : datalen);
332 bus_read_region_4(chp->ch_mem,
333 LC_SMIT_OFFSET, (u_int32_t *) data, count >> 2);
339 bs->sc_edatalen = datalen;
345 if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE))
347 if (cti->cti_syncreg == 0)
350 * If async transfer, reconfirm a scsi phase
351 * again. Unless C bus might hang up.
353 if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE))
357 count = (datalen > LC_SFSZ ? LC_SFSZ : datalen);
358 bus_write_region_4(chp->ch_mem,
359 LC_SMIT_OFFSET, (u_int32_t *) data, count >> 2);
363 if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE))
366 count = (datalen > LC_REST ? LC_REST : datalen);
367 bus_write_region_4(chp->ch_mem,
368 LC_SMIT_OFFSET + LC_SFSZ,
369 (u_int32_t *) data, count >> 2);
378 /*********************************************************
380 *********************************************************/
381 static __inline void bshw_dma_write_1 \
382 (struct ct_bus_access_handle *, bus_addr_t, u_int8_t);
383 static void bshw_dmastart(struct ct_softc *);
384 static void bshw_dmadone(struct ct_softc *);
387 bshw_dma_xfer_start(struct ct_softc *ct)
389 struct scsi_low_softc *slp = &ct->sc_sclow;
390 struct sc_p *sp = &slp->sl_scp;
391 struct ct_bus_access_handle *chp = &ct->sc_ch;
392 struct bshw_softc *bs = ct->ct_hw;
393 vaddr_t va, endva, phys, nphys;
396 io_control = bs->sc_io_control | bshw_io_control;
397 if ((io_control & BSHW_DMA_BLOCK) != 0 && sp->scp_datalen < 256)
400 ct_cr_write_1(chp, wd3s_ctrl, ct->sc_creg | CR_DMA);
401 phys = vtophys((vaddr_t) sp->scp_data);
402 if (phys >= bs->sc_minphys)
405 bs->sc_segaddr = bs->sc_bounce_phys;
407 bs->sc_seglen = sp->scp_datalen;
408 if (bs->sc_seglen > bs->sc_bounce_size)
409 bs->sc_seglen = bs->sc_bounce_size;
411 bs->sc_bufp = bs->sc_bounce_addr;
412 if (sp->scp_direction == SCSI_LOW_WRITE)
413 bcopy(sp->scp_data, bs->sc_bufp, bs->sc_seglen);
418 bs->sc_segaddr = (u_int8_t *) phys;
420 endva = (vaddr_t) round_page((vaddr_t) sp->scp_data + sp->scp_datalen);
421 for (va = (vaddr_t) sp->scp_data; ; phys = nphys)
423 if ((va += PAGE_SIZE) >= endva)
425 bs->sc_seglen = sp->scp_datalen;
430 if (phys + PAGE_SIZE != nphys || nphys >= bs->sc_minphys)
433 (u_int8_t *) trunc_page(va) - sp->scp_data;
442 cthw_set_count(chp, bs->sc_seglen);
443 ct_cr_write_1(chp, wd3s_cmd, WD3S_TFR_INFO);
448 bshw_dma_xfer_stop(struct ct_softc *ct)
450 struct scsi_low_softc *slp = &ct->sc_sclow;
451 struct sc_p *sp = &slp->sl_scp;
452 struct bshw_softc *bs = ct->ct_hw;
453 struct targ_info *ti;
454 u_int count, transbytes;
462 if (ti->ti_phase == PH_DATA)
464 count = cthw_get_count(&ct->sc_ch);
465 if (count < (u_int) bs->sc_seglen)
467 transbytes = bs->sc_seglen - count;
468 if (bs->sc_bufp != NULL &&
469 sp->scp_direction == SCSI_LOW_READ)
470 bcopy(bs->sc_bufp, sp->scp_data, transbytes);
472 sp->scp_data += transbytes;
473 sp->scp_datalen -= transbytes;
475 else if (count > (u_int) bs->sc_seglen)
477 device_printf(slp->sl_dev,
478 "port data %x != seglen %x\n",
479 count, bs->sc_seglen);
480 slp->sl_error |= PDMAERR;
483 scsi_low_data_finish(slp);
487 device_printf(slp->sl_dev, "extra DMA interrupt\n");
488 slp->sl_error |= PDMAERR;
494 /* common dma settings */
496 #define DMA1_SMSK (0x15)
498 #define DMA1_MODE (0x17)
500 #define DMA1_FFC (0x19)
502 #define DMA1_CHN(c) (0x01 + ((c) << 2))
504 #define DMA37SM_SET 0x04
505 #define DMA37MD_WRITE 0x04
506 #define DMA37MD_READ 0x08
507 #define DMA37MD_SINGLE 0x40
509 static bus_addr_t dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 };
512 bshw_dma_write_1(struct ct_bus_access_handle *chp, bus_addr_t port,
521 bshw_dmastart(struct ct_softc *ct)
523 struct scsi_low_softc *slp = &ct->sc_sclow;
524 struct bshw_softc *bs = ct->ct_hw;
525 struct ct_bus_access_handle *chp = &ct->sc_ch;
526 int chan = bs->sc_drq;
528 u_int8_t regv, *phys = bs->sc_segaddr;
529 u_int nbytes = bs->sc_seglen;
531 /* flush cpu cache */
532 (*bs->sc_dmasync_before) (ct);
535 * Program one of DMA channels 0..3. These are
536 * byte mode channels.
538 /* set dma channel mode, and reset address ff */
540 if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
541 regv = DMA37MD_WRITE | DMA37MD_SINGLE | chan;
543 regv = DMA37MD_READ | DMA37MD_SINGLE | chan;
545 bshw_dma_write_1(chp, DMA1_MODE, regv);
546 bshw_dma_write_1(chp, DMA1_FFC, 0);
548 /* send start address */
549 waport = DMA1_CHN(chan);
550 bshw_dma_write_1(chp, waport, (u_int) phys);
551 bshw_dma_write_1(chp, waport, ((u_int) phys) >> 8);
552 bshw_dma_write_1(chp, dmapageport[chan], ((u_int) phys) >> 16);
555 bshw_dma_write_1(chp, waport + 2, --nbytes);
556 bshw_dma_write_1(chp, waport + 2, nbytes >> 8);
558 /* vendor unique hook */
559 if (bs->sc_hw->hw_dma_start)
560 (*bs->sc_hw->hw_dma_start)(ct);
562 bshw_dma_write_1(chp, DMA1_SMSK, chan);
563 ct_cmdp_write_1(chp, CMDP_DMES);
567 bshw_dmadone(struct ct_softc *ct)
569 struct bshw_softc *bs = ct->ct_hw;
570 struct ct_bus_access_handle *chp = &ct->sc_ch;
572 bshw_dma_write_1(chp, DMA1_SMSK, (bs->sc_drq | DMA37SM_SET));
573 ct_cmdp_write_1(chp, CMDP_DMER);
575 /* vendor unique hook */
576 if (bs->sc_hw->hw_dma_stop)
577 (*bs->sc_hw->hw_dma_stop) (ct);
579 /* flush cpu cache */
580 (*bs->sc_dmasync_after) (ct);
583 /**********************************************
584 * VENDOR UNIQUE DMA FUNCS
585 **********************************************/
586 static int bshw_dma_init_sc98(struct ct_softc *);
587 static void bshw_dma_start_sc98(struct ct_softc *);
588 static void bshw_dma_stop_sc98(struct ct_softc *);
589 static int bshw_dma_init_texa(struct ct_softc *);
590 static void bshw_dma_start_elecom(struct ct_softc *);
591 static void bshw_dma_stop_elecom(struct ct_softc *);
594 bshw_dma_init_texa(struct ct_softc *ct)
596 struct ct_bus_access_handle *chp = &ct->sc_ch;
599 if ((regval = ct_cr_read_1(chp, 0x37)) & 0x08)
602 ct_cr_write_1(chp, 0x37, regval | 0x08);
603 regval = ct_cr_read_1(chp, 0x3f);
604 ct_cr_write_1(chp, 0x3f, regval | 0x08);
609 bshw_dma_init_sc98(struct ct_softc *ct)
611 struct ct_bus_access_handle *chp = &ct->sc_ch;
613 if (ct_cr_read_1(chp, 0x37) & 0x08)
616 /* If your card is SC98 with bios ver 1.01 or 1.02 under no PCI */
617 ct_cr_write_1(chp, 0x37, 0x1a);
618 ct_cr_write_1(chp, 0x3f, 0x1a);
620 /* only valid for IO */
621 ct_cr_write_1(chp, 0x40, 0xf4);
622 ct_cr_write_1(chp, 0x41, 0x9);
623 ct_cr_write_1(chp, 0x43, 0xff);
624 ct_cr_write_1(chp, 0x46, 0x4e);
626 ct_cr_write_1(chp, 0x48, 0xf4);
627 ct_cr_write_1(chp, 0x49, 0x9);
628 ct_cr_write_1(chp, 0x4b, 0xff);
629 ct_cr_write_1(chp, 0x4e, 0x4e);
635 bshw_dma_start_sc98(struct ct_softc *ct)
637 struct ct_bus_access_handle *chp = &ct->sc_ch;
639 ct_cr_write_1(chp, 0x73, 0x32);
640 ct_cr_write_1(chp, 0x74, 0x23);
644 bshw_dma_stop_sc98(struct ct_softc *ct)
646 struct ct_bus_access_handle *chp = &ct->sc_ch;
648 ct_cr_write_1(chp, 0x73, 0x43);
649 ct_cr_write_1(chp, 0x74, 0x34);
653 bshw_dma_start_elecom(struct ct_softc *ct)
655 struct ct_bus_access_handle *chp = &ct->sc_ch;
656 u_int8_t tmp = ct_cr_read_1(chp, 0x4c);
658 ct_cr_write_1(chp, 0x32, tmp & 0xdf);
662 bshw_dma_stop_elecom(struct ct_softc *ct)
664 struct ct_bus_access_handle *chp = &ct->sc_ch;
665 u_int8_t tmp = ct_cr_read_1(chp, 0x4c);
667 ct_cr_write_1(chp, 0x32, tmp | 0x20);
670 static struct bshw bshw_generic = {
680 static struct bshw bshw_sc98 = {
690 static struct bshw bshw_texa = {
700 static struct bshw bshw_elecom = {
706 bshw_dma_start_elecom,
707 bshw_dma_stop_elecom,
710 static struct bshw bshw_lc_smit = {
711 BSHW_SMFIFO | BSHW_DOUBLE_DMACHAN,
720 static struct bshw bshw_lha20X = {
731 static dvcfg_hw_t bshw_hwsel_array[] = {
732 /* 0x00 */ &bshw_generic,
733 /* 0x01 */ &bshw_sc98,
734 /* 0x02 */ &bshw_texa,
735 /* 0x03 */ &bshw_elecom,
736 /* 0x04 */ &bshw_lc_smit,
737 /* 0x05 */ &bshw_lha20X,
740 struct dvcfg_hwsel bshw_hwsel = {
741 DVCFG_HWSEL_SZ(bshw_hwsel_array),