Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / sys / dev / disk / i386 / bs / bshw.c
1 /*      $NecBSD: bshw.c,v 1.1 1997/07/18 09:19:03 kmatsuda Exp $        */
2 /*      $NetBSD$        */
3 /*
4  * [NetBSD for NEC PC98 series]
5  *  Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
6  *  All rights reserved.
7  * 
8  *  Redistribution and use in source and binary forms, with or without
9  *  modification, are permitted provided that the following conditions
10  *  are met:
11  *  1. Redistributions of source code must retain the above copyright
12  *     notice, this list of conditions and the following disclaimer.
13  *  2. Redistributions in binary form must reproduce the above copyright
14  *     notice, this list of conditions and the following disclaimer in the
15  *     documentation and/or other materials provided with the distribution.
16  *  3. The name of the author may not be used to endorse or promote products
17  *     derived from this software without specific prior written permission.
18  * 
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 /*
32  * Copyright (c) 1994, 1995, 1996 Naofumi HONDA.  All rights reserved.
33  *
34  * $FreeBSD: src/sys/i386/isa/bs/bshw.c,v 1.7.2.1 2001/07/26 02:32:18 nyan Exp $
35  * $DragonFly: src/sys/dev/disk/i386/bs/Attic/bshw.c,v 1.2 2003/06/17 04:28:37 dillon Exp $
36  */
37
38 #ifdef  __NetBSD__
39 #include <dev/isa/isadmareg.h>
40 #include <i386/Cbus/dev/bs/bsif.h>
41 #include <i386/Cbus/dev/bs/bshw.lst>
42 #endif
43 #ifdef  __FreeBSD__
44 #include "opt_pc98.h"
45 #include <i386/isa/ic/i8237.h>
46 #include <i386/isa/bs/bsif.h>
47 #include <i386/isa/bs/bshw.lst>
48 #include <machine/clock.h>
49 #include <sys/cons.h>
50 #endif
51
52 static struct bs_softc *gbsc;
53
54 /**************************************************
55  * DECLARATION
56  **************************************************/
57 static void bshw_force_bsmode __P((struct bs_softc *));
58
59 /**************************************************
60  * STATIC VAL
61  **************************************************/
62 static int irq_tbl[] = { 3, 5, 6, 9, 12, 13 };
63
64 /**************************************************
65  * SCSI CMD BRANCH
66  **************************************************/
67 #define RS      (BSSAT | BSSMIT | BSLINK | BSREAD)
68 #define WS      (BSSAT | BSSMIT | BSLINK)
69 #define EOK     (BSERROROK)
70
71 u_int8_t bshw_cmd[256] = {
72 /*   0  1   2   3   4   5   6   7   8   9   A   B   C   E   D   F */
73 /*0*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,RS ,0  ,WS ,0  ,0  ,0  ,0  ,0  ,
74 /*1*/0  ,0  ,EOK,0  ,0  ,0  ,0  ,0  ,0  ,0  ,EOK,0  ,0  ,0  ,0  ,0  ,
75 /*2*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,RS ,0  ,WS ,0  ,0  ,0  ,0  ,0  ,
76 /*3*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
77 /*4*/0  ,0  ,EOK,EOK,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
78 /*5*/0  ,0  ,0  ,0  ,EOK,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
79 /*6*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
80 /*7*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
81 /*8*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
82 /*9*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
83 /*A*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
84 /*B*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
85 /*C*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
86 /*D*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
87 /*E*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
88 /*F*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
89 };
90
91 #undef  RS
92 #undef  WS
93 #undef  EOK
94
95 /**********************************************
96  * init
97  **********************************************/
98 static void
99 bshw_force_bsmode(bsc)
100         struct bs_softc *bsc;
101 {
102
103         if (bsc->sc_flags & BSBSMODE)
104                 return;
105         bsc->sc_flags |= BSBSMODE;
106
107         /*
108          * If you have memory over 16M, some stupid boards always force to
109          * use the io polling mode. Check such a case and change mode into
110          * bus master DMA. However this depends heavily on the board's
111          * specifications!
112          */
113
114         if (bsc->sc_hw->dma_init && ((*bsc->sc_hw->dma_init)(bsc)))
115                 printf("%s change mode using external DMA (%x)\n",
116                     bsc->sc_dvname, (u_int)read_wd33c93(bsc, 0x37));
117 }
118
119 #define RESET_DEFAULT   2000
120
121 int
122 bshw_chip_reset(bsc)
123         struct bs_softc *bsc;
124 {
125         int ct;
126         u_int8_t aux;
127
128         bshw_lock(bsc);
129
130         bshw_abort_cmd(bsc);
131         delay(10000);
132
133         bshw_get_auxstat(bsc);
134         bshw_get_busstat(bsc);
135
136         write_wd33c93(bsc, wd3s_oid, IDR_EHP | bsc->sc_cspeed | bsc->sc_hostid);
137         write_wd33c93(bsc, wd3s_cmd, WD3S_RESET);
138
139         for (ct = RESET_DEFAULT; ct > 0; ct--)
140         {
141                 aux = bshw_get_auxstat(bsc);
142                 if (aux != 0xff && (aux & STR_INT))
143                 {
144                         if (bshw_get_busstat(bsc) == 0)
145                                 break;
146
147                         write_wd33c93(bsc, wd3s_cmd, WD3S_RESET);
148                 }
149                 delay(1);
150         }
151
152         if (ct == 0)
153         {
154                 bshw_unlock(bsc);
155                 return ENXIO;
156         }
157
158         bshw_force_bsmode(bsc);
159
160         write_wd33c93(bsc, wd3s_tout, BSHW_SEL_TIMEOUT);
161         write_wd33c93(bsc, wd3s_sid, SIDR_RESEL);
162         bsc->sc_flags |= BSDMATRANSFER;
163         write_wd33c93(bsc, wd3s_ctrl, CR_DEFAULT);
164         write_wd33c93(bsc, wd3s_synch, 0);
165
166         bshw_get_auxstat(bsc);
167         bsc->sc_busstat = bshw_get_busstat(bsc);
168         bshw_unlock(bsc);
169
170         return 0;
171 }
172
173 /* scsi bus hard reset */
174 #define TWIDDLEWAIT     10000
175 static int tw_pos;
176 static char tw_chars[] = "|/-\\";
177
178 /* this is some jokes */
179 static void
180 twiddle_wait(void)
181 {
182
183         cnputc('\b');
184         cnputc(tw_chars[tw_pos++]);
185         tw_pos %= (sizeof(tw_chars) - 1);
186         delay(TWIDDLEWAIT);
187 }
188
189 static void bshw_set_vsp __P((struct bs_softc *, u_int, u_int8_t));
190
191 static void
192 bshw_set_vsp(bsc, chan, spva)
193         struct bs_softc *bsc;
194         u_int chan;
195         u_int8_t spva;
196 {
197         struct bshw *hw = bsc->sc_hw;
198
199         if (hw->sregaddr == 0)
200                 return;
201
202         write_wd33c93(bsc, hw->sregaddr + chan, spva);
203         if (hw->hw_flags & BSHW_DOUBLE_DMACHAN)
204                 write_wd33c93(bsc, hw->sregaddr + chan + 8, spva);
205 }
206
207 void
208 bshw_bus_reset(bsc)
209         struct bs_softc *bsc;
210 {
211         struct targ_info *ti;
212         int i, lpc;
213
214         if (bsc->sc_RSTdelay == 0)
215                 bsc->sc_RSTdelay = 6 * 1000 * 1000;
216         else
217         {
218                 /* XXX:
219                  * second time reset will be requested by hardware failuer.
220                  */
221                 bsc->sc_RSTdelay = 12 * 1000 * 1000;
222         }
223
224         bshw_lock(bsc);
225         write_wd33c93(bsc, wd3s_mbank, (bsc->sc_membank | MBR_RST) & ~MBR_IEN);
226         delay(500000);
227         write_wd33c93(bsc, wd3s_mbank, (bsc->sc_membank) & ~MBR_IEN);
228         bshw_unlock(bsc);
229
230         for (lpc = 0; lpc < 2; lpc ++)
231         {
232                 cnputc(' ');
233                 for (i = 0; i <= bsc->sc_RSTdelay / TWIDDLEWAIT; i++)
234                         twiddle_wait();
235                 cnputc('\b');
236
237                 (void) read_wd33c93(bsc, wd3s_auxc);
238
239                 delay(10000);
240
241                 if ((read_wd33c93(bsc, wd3s_auxc) & AUXCR_RRST) == 0)
242                         break;
243
244                 printf("\nreset state still continue, wait ...");
245         }
246
247         for (i = 0; i < NTARGETS; i++)
248         {
249                 if ((ti = bsc->sc_ti[i]) != NULL)
250                 {
251                         ti->ti_sync = 0;
252                         bshw_set_vsp(bsc, i, 0);
253                 }
254         }
255 }
256
257 /* probe */
258 int
259 bshw_board_probe(bsc, drq, irq)
260         struct bs_softc *bsc;
261         u_int *drq;
262         u_int *irq;
263 {
264
265         gbsc = bsc;
266 #ifdef  SHOW_PORT
267         bshw_print_port(bsc);
268 #endif  /* SHOW_PORT */
269
270         bsc->sc_hostid = (read_wd33c93(bsc, wd3s_auxc) & AUXCR_HIDM);
271
272         if ((*irq) == IRQUNK)
273                 *irq = irq_tbl[(read_wd33c93(bsc, wd3s_auxc) >> 3) & 7];
274
275         if ((*drq) == DRQUNK)
276                 *drq = BUS_IOR(cmd_port) & 3;
277
278         bsc->sc_dmachan = *drq;
279         bsc->sc_irq = (*irq);
280
281         bsc->sc_membank = read_wd33c93(bsc, wd3s_mbank);
282         bsc->sc_membank &= ~MBR_RST;
283         bsc->sc_membank |= MBR_IEN;
284
285         bsc->sc_cspeed = (read_wd33c93(bsc, wd3s_oid) & (~IDR_IDM));
286         switch (BSC_CHIP_CLOCK(bsc->sc_cfgflags))
287         {
288         case 0:
289                 break;
290
291         case 1:
292                 bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_16_20);
293                 break;
294
295         case 2:
296                 bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_16_20);
297                 bsc->sc_cspeed |= IDR_FS_12_15;
298                 break;
299
300         case 3:
301                 bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_16_20);
302                 bsc->sc_cspeed |= IDR_FS_16_20;
303                 break;
304         }
305
306         /* XXX: host id fixed(7) */
307         bsc->sc_hostid = 7;
308
309         if (bshw_chip_reset(bsc))
310                 return ENXIO;
311
312         return 0;
313 }
314
315 /*
316  * XXX:
317  * Assume the board clock rate must be 20Mhz (always satisfied, maybe)!
318  * Only 10M/s 6.6M/s 5.0M/s 3.3M/s for synchronus transfer speed set.
319  */
320 #define ILLEGAL_SYNCH
321 #ifdef  ILLEGAL_SYNCH
322 /*  A  10    6.6   5.0   4.0   3.3   2.8   2.5   2.0  M/s */
323 /*  X  100   150   200   250   300   350   400   500  ns  */
324 static u_int bshw_scsi_period[] =
325    {0, 25,   37,   50,   62,   75,   87,   100,  125};
326 static u_int8_t bshw_chip_pval[] =
327    {0, 0xa0, 0xb0, 0x20, 0xd0, 0x30, 0xf0, 0x40, 0x50};
328 #else   /* !ILLEGAL_SYNCH */
329 /*  A  10    6.6   5.0   3.3   2.5 M/s */
330 /*  X  100   150   200   300   400 ns  */
331 static u_int bshw_scsi_period[] =
332    {0, 25,   37,   50,   75,   100};
333 static u_int8_t bshw_chip_pval[] =
334    {0, 0xa0, 0xb0, 0x20, 0x30, 0x40};
335 #endif  /* !ILLEGAL_SYNCH */
336
337 void
338 bshw_adj_syncdata(sdp)
339         struct syncdata *sdp;
340 {
341         int i;
342
343         if (sdp->offset == 0 || sdp->period < 25 || sdp->period > 100)
344                 sdp->offset = sdp->period = 0;
345         else
346         {
347                 for (i = 0; sdp->period > bshw_scsi_period[i] + 2; i ++)
348                         ;
349                 sdp->period = bshw_scsi_period[i];
350         }
351 }
352
353 void
354 bshw_set_synchronous(bsc, ti)
355         struct bs_softc *bsc;
356         struct targ_info *ti;
357 {
358         struct syncdata sd;
359         int i;
360
361         sd = ti->ti_syncnow;
362         bshw_adj_syncdata(&sd);
363         for (i = 0; sd.period != bshw_scsi_period[i]; i++)
364                 ;
365
366         ti->ti_sync = ((sd.offset & 0x0f) | bshw_chip_pval[i]);
367         bshw_set_vsp(bsc, ti->ti_id, ti->ti_sync);
368
369         if (bsc->sc_nexus == ti)
370                 bshw_set_sync_reg(bsc, ti->ti_sync);
371 }
372
373 /* ctrl reg */
374 void
375 bshw_setup_ctrl_reg(bsc, flags)
376         struct bs_softc *bsc;
377         u_int flags;
378 {
379         u_int8_t regval;
380
381         regval = (flags & BS_SCSI_NOPARITY) ? CR_DEFAULT : CR_DEFAULT_HP;
382         if (bsc->sc_flags & BSDMATRANSFER)
383                 regval |= CR_DMA;
384         write_wd33c93(bsc, wd3s_ctrl, regval);
385 }
386
387 /* sat command */
388 void
389 bshw_issue_satcmd(bsc, cb, link)
390         struct bs_softc *bsc;
391         struct bsccb *cb;
392         int link;
393 {
394         int i;
395
396         BUS_IOW(addr_port, wd3s_cdb);
397         for (i = 0; i < cb->cmdlen - 1; i++)
398                 BUS_IOW(ctrl_port, cb->cmd[i]);
399         BUS_IOW(ctrl_port, cb->cmd[i] | (link ? 1 : 0));
400 }
401
402 /* lock */
403 void
404 bshw_lock(bsc)
405         struct bs_softc *bsc;
406 {
407
408         bsc->sc_hwlock++;
409         write_wd33c93(bsc, wd3s_mbank, bsc->sc_membank & (~MBR_IEN));
410 }
411
412 void
413 bshw_unlock(bsc)
414         struct bs_softc *bsc;
415 {
416
417         if ((--bsc->sc_hwlock) <= 0)
418                 write_wd33c93(bsc, wd3s_mbank, bsc->sc_membank);
419 }
420
421 /**********************************************
422  * DMA OPERATIONS
423  **********************************************/
424 #ifdef  __NetBSD__
425 #include <i386/Cbus/dev/bs/bshw_dma.c>
426 #include <i386/Cbus/dev/bs/bshw_pdma.c>
427 #endif
428 #ifdef  __FreeBSD__
429 #include <i386/isa/bs/bshw_dma.c>
430 #include <i386/isa/bs/bshw_pdma.c>
431 #endif
432
433 /**********************************************
434  * DEBUG
435  **********************************************/
436 /* misc */
437 void
438 bshw_print_port(bsc)
439         struct bs_softc * bsc;
440 {
441         int i, j;
442         int port = 0x0;
443
444         if (bsc == NULL)
445                 bsc = gbsc;
446
447         printf("\n");
448         for (j = 0; j <= 0x70; j += 0x10)
449         {
450                 printf("port %x: ", port);
451                 for (i = 0; i < 0x10; i++)
452                         printf("%x ", (u_int) read_wd33c93(bsc, port++));
453                 printf("\n");
454         }
455 }