1 /* $FreeBSD: releng/5.0/sys/dev/ct/bshw_machdep.c 92739 2002-03-20 02:08:01Z alfred $ */
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
94 u_int bshw_io_control = BSHW_IO_CONTROL_FLAGS;
95 int bshw_data_read_bytes = 4096;
96 int 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
107 typedef unsigned long vaddr_t;
108 #endif /* __FreeBSD__ */
109
110 /*********************************************************
111 * GENERIC MACHDEP FUNCTIONS
112 *********************************************************/
113 void
114 bshw_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
134 void
135 bshw_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 */
183 int
184 bshw_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
213 static __inline void bshw_lc_smit_start(struct ct_softc *, int, u_int);
214 static __inline void bshw_lc_smit_stop(struct ct_softc *);
215 static int bshw_lc_smit_fstat(struct ct_softc *, int, int);
216
217 static __inline void
218 bshw_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
227 static __inline void
228 bshw_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
246 static int
247 bshw_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
278 void
279 bshw_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 {
312 bad:
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
325 int
326 bshw_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 *********************************************************/
424 static __inline void bshw_dma_write_1 \
425 (struct ct_bus_access_handle *, bus_addr_t, u_int8_t);
426 static void bshw_dmastart(struct ct_softc *);
427 static void bshw_dmadone(struct ct_softc *);
428
429 int
430 bshw_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
491 void
492 bshw_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
553 static bus_addr_t dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 };
554
555 static __inline void
556 bshw_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
566 static void
567 bshw_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
613 static void
614 bshw_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 **********************************************/
634 static int bshw_dma_init_sc98(struct ct_softc *);
635 static void bshw_dma_start_sc98(struct ct_softc *);
636 static void bshw_dma_stop_sc98(struct ct_softc *);
637 static int bshw_dma_init_texa(struct ct_softc *);
638 static void bshw_dma_start_elecom(struct ct_softc *);
639 static void bshw_dma_stop_elecom(struct ct_softc *);
640
641 static int
642 bshw_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
657 static int
658 bshw_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
684 static void
685 bshw_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
694 static void
695 bshw_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
704 static void
705 bshw_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
714 static void
715 bshw_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
724 static struct bshw bshw_generic = {
725 BSHW_SYNC_RELOAD,
726
727 0,
728
729 NULL,
730 NULL,
731 NULL,
732 };
733
734 static 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
744 static struct bshw bshw_texa = {
745 BSHW_DOUBLE_DMACHAN,
746
747 0x60,
748
749 bshw_dma_init_texa,
750 NULL,
751 NULL,
752 };
753
754 static struct bshw bshw_elecom = {
755 0,
756
757 0x38,
758
759 NULL,
760 bshw_dma_start_elecom,
761 bshw_dma_stop_elecom,
762 };
763
764 static struct bshw bshw_lc_smit = {
765 BSHW_SMFIFO | BSHW_DOUBLE_DMACHAN,
766
767 0x60,
768
769 NULL,
770 NULL,
771 NULL,
772 };
773
774 static struct bshw bshw_lha20X = {
775 BSHW_DOUBLE_DMACHAN,
776
777 0x60,
778
779 NULL,
780 NULL,
781 NULL,
782 };
783
784 /* hw tabs */
785 static 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
794 struct dvcfg_hwsel bshw_hwsel = {
795 DVCFG_HWSEL_SZ(bshw_hwsel_array),
796 bshw_hwsel_array
797 };
Cache object: 64b5fbaa3da8c51a2f640fd50b2827c0
|