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