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