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$");
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#include <sys/rman.h>
50
51#include <vm/vm.h>
52
53#include <machine/bus.h>
54#include <machine/md_var.h>
55
56#include <compat/netbsd/dvcfg.h>
57
58#include <cam/scsi/scsi_low.h>
59
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>
64
65#include <vm/pmap.h>
66
67#define	BSHW_IO_CONTROL_FLAGS	0
68
69u_int bshw_io_control = BSHW_IO_CONTROL_FLAGS;
70int bshw_data_read_bytes = 4096;
71int bshw_data_write_bytes = 4096;
72
73/*********************************************************
74 * OS dep part
75 *********************************************************/
76typedef	unsigned long vaddr_t;
77
78/*********************************************************
79 * GENERIC MACHDEP FUNCTIONS
80 *********************************************************/
81void
82bshw_synch_setup(struct ct_softc *ct, struct targ_info *ti)
83{
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;
88
89	if (hw->hw_sregaddr == 0)
90		return;
91
92	ct_cr_write_1(chp, hw->hw_sregaddr + ti->ti_id, cti->cti_syncreg);
93	if (hw->hw_flags & BSHW_DOUBLE_DMACHAN)
94	{
95		ct_cr_write_1(chp, hw->hw_sregaddr + ti->ti_id + 8,
96			      cti->cti_syncreg);
97	}
98}
99
100void
101bshw_bus_reset(struct ct_softc *ct)
102{
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;
107	bus_addr_t offs;
108	u_int8_t regv;
109	int i;
110
111	/* open hardware busmaster mode */
112	if (hw->hw_dma_init != NULL && ((*hw->hw_dma_init)(ct)) != 0)
113	{
114		device_printf(slp->sl_dev,
115		    "change mode using external DMA (%x)\n",
116		    (u_int)ct_cr_read_1(chp, 0x37));
117	}
118
119	/* clear hardware synch registers */
120	offs = hw->hw_sregaddr;
121	if (offs != 0)
122	{
123		for (i = 0; i < 8; i ++, offs ++)
124		{
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);
128		}
129	}
130
131	/* disable interrupt & assert reset */
132	regv = ct_cr_read_1(chp, wd3s_mbank);
133	regv |= MBR_RST;
134	regv &= ~MBR_IEN;
135	ct_cr_write_1(chp, wd3s_mbank, regv);
136
137	DELAY(500000);
138
139	/* reset signal off */
140	regv &= ~MBR_RST;
141	ct_cr_write_1(chp, wd3s_mbank, regv);
142
143	/* interrupt enable */
144	regv |= MBR_IEN;
145	ct_cr_write_1(chp, wd3s_mbank, regv);
146}
147
148/* probe */
149int
150bshw_read_settings(struct ct_bus_access_handle *chp, struct bshw_softc *bs)
151{
152	static int irq_tbl[] = { 3, 5, 6, 9, 12, 13 };
153
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;
157	return 0;
158}
159
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
166#define	LC_SFSZ		0x0c
167#define	LC_REST		(LC_FSZ - LC_SFSZ)
168
169#define	BSHW_LC_FSET	0x36
170#define	BSHW_LC_FCTRL	0x44
171#define	FCTRL_EN	0x01
172#define	FCTRL_WRITE	0x02
173
174#define	SF_ABORT	0x08
175#define	SF_RDY		0x10
176
177static __inline void bshw_lc_smit_start(struct ct_softc *, int, u_int);
178static __inline void bshw_lc_smit_stop(struct ct_softc *);
179static int bshw_lc_smit_fstat(struct ct_softc *, int, int);
180
181static __inline void
182bshw_lc_smit_stop(struct ct_softc *ct)
183{
184	struct ct_bus_access_handle *chp = &ct->sc_ch;
185
186	ct_cr_write_1(chp, BSHW_LC_FCTRL, 0);
187	ct_cmdp_write_1(chp, CMDP_DMER);
188}
189
190static __inline void
191bshw_lc_smit_start(struct ct_softc *ct, int count, u_int direction)
192{
193	struct ct_bus_access_handle *chp = &ct->sc_ch;
194	u_int8_t pval, val;
195
196	val = ct_cr_read_1(chp, BSHW_LC_FSET);
197	cthw_set_count(chp, count);
198
199	pval = FCTRL_EN;
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);
204}
205
206static int
207bshw_lc_smit_fstat(struct ct_softc *ct, int wc, int read)
208{
209	struct ct_bus_access_handle *chp = &ct->sc_ch;
210	u_int8_t stat;
211
212	while (wc -- > 0)
213	{
214		chp->ch_bus_weight(chp);
215		stat = ct_cmdp_read_1(chp);
216		if (read == SCSI_LOW_READ)
217		{
218			if ((stat & SF_RDY) != 0)
219				return 0;
220			if ((stat & SF_ABORT) != 0)
221				return EIO;
222		}
223		else
224		{
225			if ((stat & SF_ABORT) != 0)
226				return EIO;
227			if ((stat & SF_RDY) != 0)
228				return 0;
229		}
230	}
231
232	device_printf(ct->sc_sclow.sl_dev, "SMIT fifo status timeout\n");
233	return EIO;
234}
235
236void
237bshw_smit_xfer_stop(struct ct_softc *ct)
238{
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;
243	u_int count;
244
245	bshw_lc_smit_stop(ct);
246
247	ti = slp->sl_Tnexus;
248	if (ti == NULL)
249		return;
250
251	if (ti->ti_phase == PH_DATA)
252	{
253		count = cthw_get_count(&ct->sc_ch);
254		if (count < bs->sc_sdatalen)
255		{
256			if (sp->scp_direction == SCSI_LOW_READ &&
257			    count != bs->sc_edatalen)
258				goto bad;
259
260			count = bs->sc_sdatalen - count;
261			if (count > (u_int) sp->scp_datalen)
262				goto bad;
263
264			sp->scp_data += count;
265			sp->scp_datalen -= count;
266		}
267		else if (count > bs->sc_sdatalen)
268		{
269bad:
270			device_printf(slp->sl_dev,
271			    "smit_xfer_end: cnt error\n");
272			slp->sl_error |= PDMAERR;
273		}
274		scsi_low_data_finish(slp);
275	}
276	else
277	{
278		device_printf(slp->sl_dev, "smit_xfer_end: phase miss\n");
279		slp->sl_error |= PDMAERR;
280	}
281}
282
283int
284bshw_smit_xfer_start(struct ct_softc *ct)
285{
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;
293	int wc;
294	u_int8_t *data;
295
296	io_control = bs->sc_io_control | bshw_io_control;
297	if ((io_control & BSHW_SMIT_BLOCK) != 0)
298		return EINVAL;
299
300	if ((slp->sl_scp.scp_datalen % DEV_BSIZE) != 0)
301		return EINVAL;
302
303	datalen = sp->scp_datalen;
304	if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
305	{
306		if ((io_control & BSHW_READ_INTERRUPT_DRIVEN) != 0 &&
307		     datalen > bshw_data_read_bytes)
308			datalen = bshw_data_read_bytes;
309	}
310	else
311	{
312	        if ((io_control & BSHW_WRITE_INTERRUPT_DRIVEN) != 0 &&
313		    datalen > bshw_data_write_bytes)
314			datalen = bshw_data_write_bytes;
315	}
316
317	bs->sc_sdatalen = datalen;
318	data = sp->scp_data;
319 	wc = LC_SMIT_TIMEOUT * 1024 * 1024;
320
321	ct_cr_write_1(chp, wd3s_ctrl, ct->sc_creg | CR_DMA);
322	bshw_lc_smit_start(ct, datalen, sp->scp_direction);
323
324	if (sp->scp_direction == SCSI_LOW_READ)
325	{
326		do
327		{
328			if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_READ))
329				break;
330
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);
334			data += count;
335			datalen -= count;
336		}
337		while (datalen > 0);
338
339		bs->sc_edatalen = datalen;
340	}
341	else
342	{
343		do
344		{
345			if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE))
346				break;
347			if (cti->cti_syncreg == 0)
348			{
349				/* XXX:
350				 * If async transfer, reconfirm a scsi phase
351				 * again. Unless C bus might hang up.
352			 	 */
353				if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE))
354					break;
355			}
356
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);
360			data += count;
361			datalen -= count;
362
363			if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE))
364				break;
365
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);
370			data += count;
371			datalen -= count;
372		}
373		while (datalen > 0);
374	}
375	return 0;
376}
377
378/*********************************************************
379 * DMA TRANSFER (BS)
380 *********************************************************/
381static __inline void bshw_dma_write_1 \
382	(struct ct_bus_access_handle *, bus_addr_t, u_int8_t);
383static void bshw_dmastart(struct ct_softc *);
384static void bshw_dmadone(struct ct_softc *);
385
386int
387bshw_dma_xfer_start(struct ct_softc *ct)
388{
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;
394	u_int io_control;
395
396	io_control = bs->sc_io_control | bshw_io_control;
397	if ((io_control & BSHW_DMA_BLOCK) != 0 && sp->scp_datalen < 256)
398		return EINVAL;
399
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)
403	{
404		/* setup segaddr */
405		bs->sc_segaddr = bs->sc_bounce_phys;
406		/* setup seglen */
407		bs->sc_seglen = sp->scp_datalen;
408		if (bs->sc_seglen > bs->sc_bounce_size)
409			bs->sc_seglen = bs->sc_bounce_size;
410		/* setup bufp */
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);
414	}
415	else
416	{
417		/* setup segaddr */
418		bs->sc_segaddr = (u_int8_t *) phys;
419		/* setup seglen */
420		endva = (vaddr_t) round_page((vaddr_t) sp->scp_data + sp->scp_datalen);
421		for (va = (vaddr_t) sp->scp_data; ; phys = nphys)
422		{
423			if ((va += PAGE_SIZE) >= endva)
424			{
425				bs->sc_seglen = sp->scp_datalen;
426				break;
427			}
428
429			nphys = vtophys(va);
430			if (phys + PAGE_SIZE != nphys || nphys >= bs->sc_minphys)
431			{
432				bs->sc_seglen =
433				    (u_int8_t *) trunc_page(va) - sp->scp_data;
434				break;
435			}
436		}
437		/* setup bufp */
438		bs->sc_bufp = NULL;
439	}
440
441	bshw_dmastart(ct);
442	cthw_set_count(chp, bs->sc_seglen);
443	ct_cr_write_1(chp, wd3s_cmd, WD3S_TFR_INFO);
444	return 0;
445}
446
447void
448bshw_dma_xfer_stop(struct ct_softc *ct)
449{
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;
455
456	bshw_dmadone(ct);
457
458 	ti = slp->sl_Tnexus;
459	if (ti == NULL)
460		return;
461
462	if (ti->ti_phase == PH_DATA)
463	{
464		count = cthw_get_count(&ct->sc_ch);
465		if (count < (u_int) bs->sc_seglen)
466		{
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);
471
472			sp->scp_data += transbytes;
473			sp->scp_datalen -= transbytes;
474		}
475		else if (count > (u_int) bs->sc_seglen)
476		{
477			device_printf(slp->sl_dev,
478			    "port data %x != seglen %x\n",
479			    count, bs->sc_seglen);
480			slp->sl_error |= PDMAERR;
481		}
482
483		scsi_low_data_finish(slp);
484	}
485	else
486	{
487		device_printf(slp->sl_dev, "extra DMA interrupt\n");
488		slp->sl_error |= PDMAERR;
489	}
490
491	bs->sc_bufp = NULL;
492}
493
494/* common dma settings */
495#undef	DMA1_SMSK
496#define DMA1_SMSK	(0x15)
497#undef	DMA1_MODE
498#define DMA1_MODE	(0x17)
499#undef	DMA1_FFC
500#define DMA1_FFC	(0x19)
501#undef	DMA1_CHN
502#define DMA1_CHN(c)	(0x01 + ((c) << 2))
503
504#define DMA37SM_SET	0x04
505#define	DMA37MD_WRITE	0x04
506#define	DMA37MD_READ	0x08
507#define	DMA37MD_SINGLE	0x40
508
509static bus_addr_t dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 };
510
511static __inline void
512bshw_dma_write_1(struct ct_bus_access_handle *chp, bus_addr_t port,
513    u_int8_t val)
514{
515
516	CT_BUS_WEIGHT(chp);
517	outb(port, val);
518}
519
520static void
521bshw_dmastart(struct ct_softc *ct)
522{
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;
527	bus_addr_t waport;
528	u_int8_t regv, *phys = bs->sc_segaddr;
529	u_int nbytes = bs->sc_seglen;
530
531	/* flush cpu cache */
532	(*bs->sc_dmasync_before) (ct);
533
534	/*
535	 * Program one of DMA channels 0..3. These are
536	 * byte mode channels.
537	 */
538	/* set dma channel mode, and reset address ff */
539
540	if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
541		regv = DMA37MD_WRITE | DMA37MD_SINGLE | chan;
542	else
543		regv = DMA37MD_READ | DMA37MD_SINGLE | chan;
544
545	bshw_dma_write_1(chp, DMA1_MODE, regv);
546	bshw_dma_write_1(chp, DMA1_FFC, 0);
547
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);
553
554	/* send count */
555	bshw_dma_write_1(chp, waport + 2, --nbytes);
556	bshw_dma_write_1(chp, waport + 2, nbytes >> 8);
557
558	/* vendor unique hook */
559	if (bs->sc_hw->hw_dma_start)
560		(*bs->sc_hw->hw_dma_start)(ct);
561
562	bshw_dma_write_1(chp, DMA1_SMSK, chan);
563	ct_cmdp_write_1(chp, CMDP_DMES);
564}
565
566static void
567bshw_dmadone(struct ct_softc *ct)
568{
569	struct bshw_softc *bs = ct->ct_hw;
570	struct ct_bus_access_handle *chp = &ct->sc_ch;
571
572	bshw_dma_write_1(chp, DMA1_SMSK, (bs->sc_drq | DMA37SM_SET));
573	ct_cmdp_write_1(chp, CMDP_DMER);
574
575	/* vendor unique hook */
576	if (bs->sc_hw->hw_dma_stop)
577		(*bs->sc_hw->hw_dma_stop) (ct);
578
579	/* flush cpu cache */
580	(*bs->sc_dmasync_after) (ct);
581}
582
583/**********************************************
584 * VENDOR UNIQUE DMA FUNCS
585 **********************************************/
586static int bshw_dma_init_sc98(struct ct_softc *);
587static void bshw_dma_start_sc98(struct ct_softc *);
588static void bshw_dma_stop_sc98(struct ct_softc *);
589static int bshw_dma_init_texa(struct ct_softc *);
590static void bshw_dma_start_elecom(struct ct_softc *);
591static void bshw_dma_stop_elecom(struct ct_softc *);
592
593static int
594bshw_dma_init_texa(struct ct_softc *ct)
595{
596	struct ct_bus_access_handle *chp = &ct->sc_ch;
597	u_int8_t regval;
598
599	if ((regval = ct_cr_read_1(chp, 0x37)) & 0x08)
600		return 0;
601
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);
605	return 1;
606}
607
608static int
609bshw_dma_init_sc98(struct ct_softc *ct)
610{
611	struct ct_bus_access_handle *chp = &ct->sc_ch;
612
613	if (ct_cr_read_1(chp, 0x37) & 0x08)
614		return 0;
615
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);
619#if	0
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);
625
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);
630#endif
631	return 1;
632}
633
634static void
635bshw_dma_start_sc98(struct ct_softc *ct)
636{
637	struct ct_bus_access_handle *chp = &ct->sc_ch;
638
639	ct_cr_write_1(chp, 0x73, 0x32);
640	ct_cr_write_1(chp, 0x74, 0x23);
641}
642
643static void
644bshw_dma_stop_sc98(struct ct_softc *ct)
645{
646	struct ct_bus_access_handle *chp = &ct->sc_ch;
647
648	ct_cr_write_1(chp, 0x73, 0x43);
649	ct_cr_write_1(chp, 0x74, 0x34);
650}
651
652static void
653bshw_dma_start_elecom(struct ct_softc *ct)
654{
655	struct ct_bus_access_handle *chp = &ct->sc_ch;
656	u_int8_t tmp = ct_cr_read_1(chp, 0x4c);
657
658	ct_cr_write_1(chp, 0x32, tmp & 0xdf);
659}
660
661static void
662bshw_dma_stop_elecom(struct ct_softc *ct)
663{
664	struct ct_bus_access_handle *chp = &ct->sc_ch;
665	u_int8_t tmp = ct_cr_read_1(chp, 0x4c);
666
667	ct_cr_write_1(chp, 0x32, tmp | 0x20);
668}
669
670static struct bshw bshw_generic = {
671	BSHW_SYNC_RELOAD,
672
673	0,
674
675	NULL,
676	NULL,
677	NULL,
678};
679
680static struct bshw bshw_sc98 = {
681	BSHW_DOUBLE_DMACHAN,
682
683	0x60,
684
685	bshw_dma_init_sc98,
686	bshw_dma_start_sc98,
687	bshw_dma_stop_sc98,
688};
689
690static struct bshw bshw_texa = {
691	BSHW_DOUBLE_DMACHAN,
692
693	0x60,
694
695	bshw_dma_init_texa,
696	NULL,
697	NULL,
698};
699
700static struct bshw bshw_elecom = {
701	0,
702
703	0x38,
704
705	NULL,
706	bshw_dma_start_elecom,
707	bshw_dma_stop_elecom,
708};
709
710static struct bshw bshw_lc_smit = {
711	BSHW_SMFIFO | BSHW_DOUBLE_DMACHAN,
712
713	0x60,
714
715	NULL,
716	NULL,
717	NULL,
718};
719
720static struct bshw bshw_lha20X = {
721	BSHW_DOUBLE_DMACHAN,
722
723	0x60,
724
725	NULL,
726	NULL,
727	NULL,
728};
729
730/* hw tabs */
731static 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,
738};
739
740struct dvcfg_hwsel bshw_hwsel = {
741	DVCFG_HWSEL_SZ(bshw_hwsel_array),
742	bshw_hwsel_array
743};
744