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