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