Initial import from FreeBSD RELENG_4:
[games.git] / sys / dev / disk / ct / bshw_machdep.c
1 /* $FreeBSD: src/sys/dev/ct/bshw_machdep.c,v 1.3.2.1 2001/07/26 02:32:18 nyan Exp $ */
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 __P((struct ct_softc *, int, u_int));
214 static __inline void bshw_lc_smit_stop __P((struct ct_softc *));
215 static int bshw_lc_smit_fstat __P((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         __P((struct ct_bus_access_handle *, bus_addr_t, u_int8_t));
426 static void bshw_dmastart __P((struct ct_softc *));
427 static void bshw_dmadone __P((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 __P((struct ct_softc *));
635 static void bshw_dma_start_sc98 __P((struct ct_softc *));
636 static void bshw_dma_stop_sc98 __P((struct ct_softc *));
637 static int bshw_dma_init_texa __P((struct ct_softc *));
638 static void bshw_dma_start_elecom __P((struct ct_softc *));
639 static void bshw_dma_stop_elecom __P((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 };