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