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