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