This source file includes following definitions.
- aha1542_stat
- aha1542_out
- makecode
- aha1542_test_port
- aha1542_info
- aha1542_intr_handle
- aha1542_queuecommand
- internal_done
- aha1542_command
- setup_mailboxes
- call_buh
- aha1542_detect
- aha1542_abort
- aha1542_reset
1
2
3
4
5
6
7 #include <linux/config.h>
8 #include <linux/kernel.h>
9 #include <linux/head.h>
10 #include <linux/types.h>
11 #include <linux/string.h>
12
13 #include <asm/system.h>
14 #include <asm/io.h>
15 #include "scsi.h"
16 #include "hosts.h"
17
18 #include "aha1542.h"
19 #ifdef DEBUG
20 #define DEB(x) x
21 #else
22 #define DEB(x)
23 #endif
24
25
26
27
28
29 #define base 0x330
30 #define intr_chan 11
31
32 static struct mailbox mb[2];
33 static struct ccb ccb;
34
35 long WAITtimeout, WAITnexttimeout = 3000000;
36
37 void (*do_done)(int, int) = NULL;
38 int aha1542_host = 0;
39 extern void aha1542_interrupt();
40
41 #define aha1542_intr_reset() outb(IRST, CONTROL)
42 #define aha1542_enable_intr() outb(inb_p(0xA1) & ~8, 0xA1)
43 #define aha1542_disable_intr() outb(inb_p(0xA1) | 8, 0xA1)
44
45 #define WAIT(port, mask, allof, noneof) \
46 { register WAITbits; \
47 register WAITtimeout = WAITnexttimeout; \
48 while (1) { \
49 WAITbits = inb(port) & (mask); \
50 if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \
51 break; \
52 if (--WAITtimeout == 0) goto fail; \
53 } \
54 }
55
56 static void aha1542_stat(void)
57 {
58
59
60 }
61
62 static int aha1542_out(unchar *cmdp, int len)
63 {
64 while (len--)
65 {
66 WAIT(STATUS, CDF, 0, CDF);
67 outb(*cmdp++, DATA);
68 }
69 return 0;
70 fail:
71 printk("aha1542_out failed(%d): ", len+1); aha1542_stat();
72 return 1;
73 }
74
75 int makecode(unsigned hosterr, unsigned scsierr)
76 {
77 switch (hosterr) {
78 case 0x0:
79 case 0xa:
80 case 0xb:
81 hosterr = 0;
82 break;
83
84 case 0x11:
85
86 hosterr = DID_TIME_OUT;
87 break;
88
89 case 0x12:
90
91
92
93 case 0x13:
94
95 case 0x15:
96
97
98 case 0x16:
99
100
101 case 0x17:
102
103
104 case 0x18:
105
106
107 case 0x19:
108
109
110
111 case 0x1a:
112
113
114 hosterr = DID_ERROR;
115 break;
116
117 case 0x14:
118
119
120
121 hosterr = DID_RESET;
122 break;
123 default:
124 printk("makecode: unknown hoststatus %x\n", hosterr);
125 break;
126 }
127 return scsierr|(hosterr << 16);
128 }
129
130 int aha1542_test_port(void)
131 {
132 volatile int debug = 0;
133
134
135
136
137
138 outb(SRST|IRST, CONTROL);
139
140 debug = 1;
141
142 WAIT(STATUS, STATMASK, INIT|IDLE, STST|DIAGF|INVDCMD|DF|CDF);
143
144 debug = 2;
145
146 if (inb(INTRFLAGS)&INTRMASK) goto fail;
147
148 debug = 3;
149
150 outb(CMD_ECHO, DATA);
151
152 debug = 4;
153
154 WAIT(STATUS, STATMASK, 0, STST|DIAGF|INVDCMD|DF|CDF);
155
156 debug = 5;
157
158 outb(42, DATA);
159
160 debug = 6;
161
162 WAIT(STATUS, STATMASK, DF, STST|DIAGF|CDF|INVDCMD);
163
164 debug = 7;
165
166 if (inb(DATA) != 42) goto fail;
167
168 debug = 8;
169
170 if (inb(STATUS) & DF) goto fail;
171
172 debug = 9;
173
174 WAIT(INTRFLAGS, HACC, HACC, 0);
175
176
177 debug = 10;
178
179 outb(IRST, CONTROL);
180
181 debug = 11;
182
183 return debug;
184 fail:
185 return 0;
186 }
187
188
189 char *aha1542_info(void)
190 {
191 static char buffer[] = "Adaptec 1542";
192 return buffer;
193 }
194
195
196 void aha1542_intr_handle(void)
197 {
198 void (*my_done)(int, int) = do_done;
199 int errstatus;
200
201 do_done = NULL;
202 #ifdef DEBUG
203 printk("aha1542_intr_handle: ");
204 if (!(flag&ANYINTR)) printk("no interrupt?");
205 if (flag&MBIF) printk("MBIF ");
206 if (flag&MBOA) printk("MBOF ");
207 if (flag&HACC) printk("HACC ");
208 if (flag&SCRD) printk("SCRD ");
209 printk("status %02x\n", inb(STATUS));
210 if (ccb.tarstat|ccb.hastat)
211 printk("aha1542_command: returning %x (status %d)\n", ccb.tarstat + ((int) ccb.hastat << 16), mb[1].status);
212 #endif
213 aha1542_intr_reset();
214 if (!my_done) {
215 printk("aha1542_intr_handle: Unexpected interrupt\n");
216 return;
217 }
218
219
220
221 if (!mb[1].status) {
222 DEB(printk("aha1542_intr_handle: strange: mbif but no mail!\n"));
223 my_done(aha1542_host, DID_TIME_OUT << 16);
224 return;
225 }
226
227
228 if (mb[1].status != 1)
229
230 errstatus = makecode(ccb.hastat, ccb.tarstat);
231 else
232 errstatus = 0;
233
234 mb[1].status = 0;
235
236 if (ccb.tarstat == 2) {
237 int i;
238 DEB(printk("aha1542_intr_handle: sense:"));
239 for (i = 0; i < 12; i++)
240 printk("%02x ", ccb.cdb[ccb.cdblen+i]);
241 printk("\n");
242
243
244
245
246
247
248 }
249 DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
250 my_done(aha1542_host, errstatus);
251 return;
252 }
253
254 int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int, int))
255 {
256 unchar ahacmd = CMD_START_SCSI;
257 unchar *cmd = (unchar *) cmnd;
258 DEB(int i);
259
260 DEB(if (target > 1) {done(aha1542_host, DID_TIME_OUT << 16); return 0;});
261
262 #ifdef DEBUG
263 if (*cmd == READ_10 || *cmd == WRITE_10)
264 i = xscsi2int(cmd+2);
265 else if (*cmd == READ_6 || *cmd == WRITE_6)
266 i = scsi2int(cmd+2);
267 else
268 i = -1;
269 if (done)
270 printk("aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
271 else
272 printk("aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
273 aha1542_stat();
274 printk("aha1542_queuecommand: dumping scsi cmd:");
275 for (i = 0; i < (*cmd<=0x1f?6:10); i++) printk("%02x ", cmd[i]);
276 printk("\n");
277 if (*cmd == WRITE_10 || *cmd == WRITE_6)
278 return 0;
279 #endif
280 memset(&ccb, 0, sizeof ccb);
281
282 ccb.cdblen = (*cmd<=0x1f)?6:10;
283
284 memcpy(ccb.cdb, cmd, ccb.cdblen);
285 ccb.op = 0;
286 ccb.idlun = (target&7)<<5;
287 ccb.rsalen = 12;
288 any2scsi(ccb.datalen, bufflen);
289 any2scsi(ccb.dataptr, buff);
290 ccb.linkptr[0] = ccb.linkptr[1] = ccb.linkptr[2] = 0;
291 ccb.commlinkid = 0;
292
293 mb[0].status = 1;
294 mb[1].status = 0;
295
296 #ifdef DEBUGd
297 printk("aha1542_command: sending.. ");
298 for (i = 0; i < sizeof(ccb)-10; i++)
299 printk("%02x ", ((unchar *)&ccb)[i]);
300 #endif
301
302 if (done) {
303 DEB(printk("aha1542_queuecommand: now waiting for interrupt "); aha1542_stat());
304 if (do_done)
305 printk("aha1542_queuecommand: Two concurrent queuecommand?\n");
306 else
307 do_done = done;
308 aha1542_out(&ahacmd, 1);
309 DEB(aha1542_stat());
310 aha1542_enable_intr();
311 }
312 else
313 printk("aha1542_queuecommand: done can't be NULL\n");
314
315 return 0;
316 }
317
318 volatile static int internal_done_flag = 0;
319 volatile static int internal_done_errcode = 0;
320 static void internal_done(int host, int errcode)
321 {
322 internal_done_errcode = errcode;
323 ++internal_done_flag;
324 }
325
326 int aha1542_command(unchar target, const void *cmnd, void *buff, int bufflen)
327 {
328 DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n"));
329 aha1542_queuecommand(target, cmnd, buff, bufflen, internal_done);
330
331 while (!internal_done_flag);
332 internal_done_flag = 0;
333 return internal_done_errcode;
334 }
335
336
337 static void setup_mailboxes()
338 {
339 static unchar cmd[5] = {CMD_MBINIT, 1};
340
341 mb[0].status = mb[1].status = 0;
342 aha1542_intr_reset();
343 any2scsi((cmd+2), mb);
344 any2scsi(mb[0].ccbptr, &ccb);
345 aha1542_out(cmd, 5);
346 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
347 while (0) {
348 fail:
349 printk("aha1542_detect: failed setting up mailboxes\n");
350 }
351 aha1542_intr_reset();
352 }
353
354
355
356 void call_buh()
357 {
358 set_intr_gate(0x2b,&aha1542_interrupt);
359 }
360
361
362 int aha1542_detect(int hostnum)
363 {
364 int i;
365
366 DEB(printk("aha1542_detect: \n"));
367
368 if (!(i = aha1542_test_port())) {
369 return 0;
370 }
371
372
373 {
374 static unchar oncmd[] = {CMD_BUSON_TIME, 5};
375 static unchar offcmd[] = {CMD_BUSOFF_TIME, 9};
376
377 aha1542_intr_reset();
378 aha1542_out(oncmd, 2);
379 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
380 aha1542_intr_reset();
381 aha1542_out(offcmd, 2);
382 WAIT(INTRFLAGS, INTRMASK, HACC, 0);
383 while (0) {
384 fail:
385 printk("aha1542_detect: setting bus on/off-time failed\n");
386 }
387 aha1542_intr_reset();
388 }
389
390 aha1542_stat();
391 setup_mailboxes();
392
393 aha1542_stat();
394
395 DEB(printk("aha1542_detect: enable interrupt channel %d\n", intr_chan));
396 call_buh();
397
398 if (intr_chan >= 8)
399 outb(inb_p(0x21)&0xfb,0x21);
400
401 DEB(printk("aha1542_detect: enabling interrupts\n"));
402 aha1542_enable_intr();
403
404 #ifdef DEBUG
405 DEB(printk(" *** READ CAPACITY ***\n"));
406
407 {
408 unchar buf[8];
409 static unchar cmd[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
410 int i;
411
412 for (i = 0; i < sizeof(buf); ++i) buf[i] = 0x87;
413 for (i = 0; i < 2; ++i)
414 if (!aha1542_command(i, cmd, buf, sizeof(buf))) {
415 printk("aha_detect: LU %d sector_size %d device_size %d\n",
416 i, xscsi2int(buf+4), xscsi2int(buf));
417 }
418 }
419
420 DEB(printk(" *** NOW RUNNING MY OWN TEST *** \n"));
421
422 for (i = 0; i < 4; ++i)
423 {
424 unsigned char cmd[10];
425 static buffer[512];
426
427 cmd[0] = READ_10;
428 cmd[1] = 0;
429 xany2scsi(cmd+2, i);
430 cmd[6] = 0;
431 cmd[7] = 0;
432 cmd[8] = 1;
433 cmd[9] = 0;
434 aha1542_command(0, cmd, buffer, 512);
435 }
436 #endif
437 aha1542_host = hostnum;
438 return 1;
439 }
440
441 int aha1542_abort(int i)
442 {
443 DEB(printk("aha1542_abort\n"));
444 return 0;
445 }
446
447 int aha1542_reset(void)
448 {
449 DEB(printk("aha1542_reset called\n"));
450 return 0;
451 }
452
453 __asm__("
454 _aha1542_interrupt:
455 cld
456 pushl %eax
457 pushl %ecx
458 pushl %edx
459 push %ds
460 push %es
461 push %fs
462 movl $0x10,%eax
463 mov %ax,%ds
464 mov %ax,%es
465 movl $0x17,%eax
466 mov %ax,%fs
467 movb $0x20,%al
468 outb %al,$0xA0 # EOI to interrupt controller #1
469 jmp 1f # give port chance to breathe
470 1: jmp 1f
471 1: outb %al,$0x20
472 # Please, someone, change this to use the timer
473 # andl $0xfffeffff,_timer_active
474 movl $_aha1542_intr_handle,%edx
475 call *%edx # ``interesting'' way of handling intr.
476 pop %fs
477 pop %es
478 pop %ds
479 popl %edx
480 popl %ecx
481 popl %eax
482 iret
483 ");