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