xref: /NextBSD/sys/dev/ct/bshw_machdep.c (revision 65145fa4c81da358fcbc3b650156dab705dfa34e)
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 
69 u_int bshw_io_control = BSHW_IO_CONTROL_FLAGS;
70 int bshw_data_read_bytes = 4096;
71 int bshw_data_write_bytes = 4096;
72 
73 /*********************************************************
74  * OS dep part
75  *********************************************************/
76 typedef	unsigned long vaddr_t;
77 
78 /*********************************************************
79  * GENERIC MACHDEP FUNCTIONS
80  *********************************************************/
81 void
bshw_synch_setup(struct ct_softc * ct,struct targ_info * ti)82 bshw_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 
100 void
bshw_bus_reset(struct ct_softc * ct)101 bshw_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 */
149 int
bshw_read_settings(struct ct_bus_access_handle * chp,struct bshw_softc * bs)150 bshw_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 
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);
180 
181 static __inline void
bshw_lc_smit_stop(struct ct_softc * ct)182 bshw_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 
190 static __inline void
bshw_lc_smit_start(struct ct_softc * ct,int count,u_int direction)191 bshw_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 
206 static int
bshw_lc_smit_fstat(struct ct_softc * ct,int wc,int read)207 bshw_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 
236 void
bshw_smit_xfer_stop(struct ct_softc * ct)237 bshw_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 		{
269 bad:
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 
283 int
bshw_smit_xfer_start(struct ct_softc * ct)284 bshw_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  *********************************************************/
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 *);
385 
386 int
bshw_dma_xfer_start(struct ct_softc * ct)387 bshw_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 
447 void
bshw_dma_xfer_stop(struct ct_softc * ct)448 bshw_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 
509 static bus_addr_t dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 };
510 
511 static __inline void
bshw_dma_write_1(struct ct_bus_access_handle * chp,bus_addr_t port,u_int8_t val)512 bshw_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 
520 static void
bshw_dmastart(struct ct_softc * ct)521 bshw_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 
566 static void
bshw_dmadone(struct ct_softc * ct)567 bshw_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  **********************************************/
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 *);
592 
593 static int
bshw_dma_init_texa(struct ct_softc * ct)594 bshw_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 
608 static int
bshw_dma_init_sc98(struct ct_softc * ct)609 bshw_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 
634 static void
bshw_dma_start_sc98(struct ct_softc * ct)635 bshw_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 
643 static void
bshw_dma_stop_sc98(struct ct_softc * ct)644 bshw_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 
652 static void
bshw_dma_start_elecom(struct ct_softc * ct)653 bshw_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 
661 static void
bshw_dma_stop_elecom(struct ct_softc * ct)662 bshw_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 
670 static struct bshw bshw_generic = {
671 	BSHW_SYNC_RELOAD,
672 
673 	0,
674 
675 	NULL,
676 	NULL,
677 	NULL,
678 };
679 
680 static 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 
690 static struct bshw bshw_texa = {
691 	BSHW_DOUBLE_DMACHAN,
692 
693 	0x60,
694 
695 	bshw_dma_init_texa,
696 	NULL,
697 	NULL,
698 };
699 
700 static struct bshw bshw_elecom = {
701 	0,
702 
703 	0x38,
704 
705 	NULL,
706 	bshw_dma_start_elecom,
707 	bshw_dma_stop_elecom,
708 };
709 
710 static struct bshw bshw_lc_smit = {
711 	BSHW_SMFIFO | BSHW_DOUBLE_DMACHAN,
712 
713 	0x60,
714 
715 	NULL,
716 	NULL,
717 	NULL,
718 };
719 
720 static struct bshw bshw_lha20X = {
721 	BSHW_DOUBLE_DMACHAN,
722 
723 	0x60,
724 
725 	NULL,
726 	NULL,
727 	NULL,
728 };
729 
730 /* hw tabs */
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,
738 };
739 
740 struct dvcfg_hwsel bshw_hwsel = {
741 	DVCFG_HWSEL_SZ(bshw_hwsel_array),
742 	bshw_hwsel_array
743 };
744