|
|
1.1 root 1: /*
2: * seagate.c Copyright (C) 1992 Drew Eckhardt
3: * low level scsi driver for ST01/ST02 by
4: * Drew Eckhardt
5: *
6: * <[email protected]>
7: */
8:
9: #include <linux/config.h>
10:
11: #ifdef CONFIG_SCSI_SEAGATE
12: #include <linux/sched.h>
13:
14: #include "seagate.h"
15: #include "scsi.h"
16: #include "hosts.h"
17:
18: static int incommand; /*
19: set if arbitration has finished and we are
20: in some command phase.
21: */
22:
23: static void *base_address = NULL; /*
24: Where the card ROM starts,
25: used to calculate memory mapped
26: register location.
27: */
28: static volatile int abort_confirm = 0;
29:
30: volatile void *st0x_cr_sr; /*
31: control register write,
32: status register read.
33: 256 bytes in length.
34:
35: Read is status of SCSI BUS,
36: as per STAT masks.
37:
38: */
39:
40:
41: static volatile void *st0x_dr; /*
42: data register, read write
43: 256 bytes in length.
44: */
45:
46:
47: static volatile int st0x_aborted=0; /*
48: set when we are aborted, ie by a time out, etc.
49: */
50:
51: /*
52: In theory, we have a nice auto
53: detect routine - but this
54: overides it.
55: */
56:
57:
58: #define retcode(result) (((result) << 16) | (message << 8) | status)
59: #define STATUS (*(unsigned char *) st0x_cr_sr)
60: #define CONTROL STATUS
61: #define DATA (*(unsigned char *) st0x_dr)
62:
63: #ifndef OVERRIDE
64: static const char * seagate_bases[] = {(char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000, (char *) 0xce000, (char *) 0xce000,
65: (char *) 0xdc000, (char *) 0xde000};
66: typedef struct
67: {
68: char *signature ;
69: unsigned offset;
70: unsigned length;
71: } Signature;
72:
73: static const Signature signatures[] = {
74: {"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40},
75: {"SEAGATE SCSI BIOS ",16, 17},
76: {"SEAGATE SCSI BIOS ",17, 17}};
77: /*
78: Note that the last signature handles BIOS revisions 3.0.0 and
79: 3.2 - the real ID's are
80:
81: SEAGATE SCSI BIOS REVISION 3.0.0
82: SEAGATE SCSI BIOS REVISION 3.2
83:
84: */
85:
86: #define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature))
87: #endif
88:
89: int seagate_st0x_detect (int hostnum)
90: {
91: #ifndef OVERRIDE
92: int i,j;
93: #endif
94:
95: /*
96: First, we try for the manual override.
97: */
98: #ifdef DEBUG
99: printk("Autodetecting seagate ST0x\n");
100: #endif
101:
102: base_address = NULL;
103: #ifdef OVERRIDE
104: base_address = (void *) OVERRIDE;
105: #ifdef DEBUG
106: printk("Base address overridden to %x\n", base_address);
107: #endif
108: #else
109: /*
110: To detect this card, we simply look for the SEAGATE SCSI
111: from the BIOS version notice in all the possible locations
112: of the ROM's.
113: */
114:
115: for (i = 0; i < (sizeof (seagate_bases) / sizeof (char * )); ++i)
116: for (j = 0; !base_address && j < NUM_SIGNATURES; ++j)
117: if (!memcmp ((void *) (seagate_bases[i] +
118: signatures[j].offset), (void *) signatures[j].signature,
119: signatures[j].length))
120: base_address = (void *) seagate_bases[i];
121: #endif
122:
123: if (base_address)
124: {
125: st0x_cr_sr =(void *) (((unsigned char *) base_address) + 0x1a00);
126: st0x_dr = (void *) (((unsigned char *) base_address )+ 0x1c00);
127: #ifdef DEBUG
128: printk("ST0x detected. Base address = %x, cr = %x, dr = %x\n", base_address, st0x_cr_sr, st0x_dr);
129: #endif
130: return -1;
131: }
132: else
133: {
134: #ifdef DEBUG
135: printk("ST0x not detected.\n");
136: #endif
137: return 0;
138: }
139: }
140:
141:
142:
143: char *seagate_st0x_info(void)
144: {
145: static char buffer[] = "Seagate ST-0X SCSI driver by Drew Eckhardt \n"
146: "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/seagate.c,v 1.1 1992/04/24 18:01:50 root Exp root $\n";
147: return buffer;
148: }
149:
150:
151:
152: int seagate_st0x_command(unsigned char target, const void *cmnd,
153: void *buff, int bufflen)
154: {
155: int len;
156: unsigned char *data;
157:
158: int clock; /*
159: We use clock for timeouts, etc. This replaces the
160: seagate_st0x_timeout that we had been using.
161: */
162: #if (DEBUG & PHASE_SELECTION)
163: int temp;
164: #endif
165:
166: #if (DEBUG & PHASE_EXIT)
167: void *retaddr, *realretaddr;
168: #endif
169:
170: #if ((DEBUG & PHASE_ETC) || (DEBUG & PRINT_COMMAND) || (DEBUG & PHASE_EXIT))
171: int i;
172: #endif
173:
174: #if (DEBUG & PHASE_ETC)
175: int phase=0, newphase;
176: #endif
177:
178: int done = 0;
179: unsigned char status = 0;
180: unsigned char message = 0;
181: register unsigned char status_read;
182:
183: #if (DEBUG & PHASE_EXIT)
184: __asm__("
185: movl 4(%%ebp), %%eax
186: ":"=a" (realretaddr):);
187: printk("return address = %08x\n", realretaddr);
188: #endif
189:
190:
191: len=bufflen;
192: data=(unsigned char *) buff;
193:
194: incommand = 0;
195: st0x_aborted = 0;
196:
197: #if (DEBUG & PRINT_COMMAND)
198: printk ("seagate_st0x_command, target = %d, command = ", target);
199: for (i = 0; i < COMMAND_SIZE(((unsigned char *)cmnd)[0]); ++i)
200: printk("%02x ", ((unsigned char *) cmnd)[i]);
201: printk("\n");
202: #endif
203:
204: if (target > 6)
205: return DID_BAD_TARGET;
206:
207:
208: #if (DEBUG & PHASE_BUS_FREE)
209: printk ("SCSI PHASE = BUS FREE \n");
210: #endif
211:
212: /*
213:
214: BUS FREE PHASE
215:
216: On entry, we make sure that the BUS is in a BUS FREE
217: phase, by insuring that both BSY and SEL are low for
218: at least one bus settle delay. The standard requires a
219: minimum of 400 ns, which is 16 clock cycles on a
220: 386-40 .
221:
222: This doesn't give us much time - so we'll do two several
223: reads to be sure be sure.
224: */
225:
226: clock = jiffies + ST0X_BUS_FREE_DELAY;
227:
228: while (((STATUS | STATUS | STATUS) &
229: (STAT_BSY | STAT_SEL)) &&
230: (!st0x_aborted) && (jiffies < clock));
231:
232: if (jiffies > clock)
233: return retcode(DID_BUS_BUSY);
234: else if (st0x_aborted)
235: return retcode(st0x_aborted);
236:
237: /*
238: Bus free has been detected, within BUS settle. I used to support an arbitration
239: phase - however, on the seagate, this degraded performance by a factor > 10 - so
240: it is no more.
241: */
242:
243: /*
244: SELECTION PHASE
245:
246: Now, we select the disk, giving it the SCSI ID at data
247: and a command of PARITY if necessary, plus driver enable,
248: plus raise select signal.
249: */
250:
251: #if (DEBUG & PHASE_SELECTION)
252: printk("SCSI PHASE = SELECTION\n");
253: #endif
254:
255: clock = jiffies + ST0X_SELECTION_DELAY;
256: DATA = (unsigned char) (1 << target);
257:
258: CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL;
259:
260: /*
261: When the SCSI device decides that we're gawking at it, it will respond by asserting BUSY on the bus.
262: */
263: while (!((status_read = STATUS) & STAT_BSY) && (jiffies < clock) && !st0x_aborted)
264:
265: #if (DEBUG & PHASE_SELECTION)
266: {
267: temp = clock - jiffies;
268:
269: if (!(jiffies % 5))
270: printk("seagate_st0x_timeout : %d \r",temp);
271:
272: }
273: printk("Done. \n\r");
274: printk("Status = %02x, seagate_st0x_timeout = %d, aborted = %02x \n", status_read, temp,
275: st0x_aborted);
276: #else
277: ;
278: #endif
279:
280:
281: if ((jiffies > clock) || (!st0x_aborted & !(status_read & STAT_BSY)))
282: {
283: #if (DEBUG & PHASE_SELECT)
284: printk ("NO CONNECT with target %d, status = %x \n", target, STATUS);
285: #endif
286: return retcode(DID_NO_CONNECT);
287: }
288:
289: /*
290: If we have been aborted, and we have a command in progress, IE the target still has
291: BSY asserted, then we will reset the bus, and notify the midlevel driver to
292: expect sense.
293: */
294:
295: if (st0x_aborted)
296: {
297: CONTROL = BASE_CMD;
298: if (STATUS & STAT_BSY)
299: {
300: seagate_st0x_reset();
301: return retcode(DID_RESET);
302: }
303:
304: return retcode(st0x_aborted);
305: }
306:
307: /*
308: COMMAND PHASE
309: The device has responded with a BSY, so we may now enter
310: the information transfer phase, where we will send / recieve
311: data and command as directed by the target.
312:
313:
314: The nasty looking read / write inline assembler loops we use for
315: DATAIN and DATAOUT phases are approximately 4-5 times as fast as
316: the 'C' versions - since we're moving 1024 bytes of data, this
317: really adds up.
318: */
319:
320: #if (DEBUG & PHASE_ETC)
321: printk("PHASE = information transfer\n");
322: #endif
323:
324: incommand = 1;
325:
326: /*
327: Enable command
328: */
329:
330: CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
331:
332: /*
333: Now, we poll the device for status information,
334: and handle any requests it makes. Note that since we are unsure of
335: how much data will be flowing across the system, etc and cannot
336: make reasonable timeouts, that we will instead have the midlevel
337: driver handle any timeouts that occur in this phase.
338: */
339:
340: while (((status_read = STATUS) & STAT_BSY) && !st0x_aborted && !done)
341: {
342: #ifdef PARITY
343: if (status_read & STAT_PARITY)
344: {
345: done = 1;
346: st0x_aborted = DID_PARITY;
347: }
348: #endif
349:
350: if (status_read & STAT_REQ)
351: {
352: #if (DEBUG & PHASE_ETC)
353: if ((newphase = (status_read & REQ_MASK)) != phase)
354: {
355: phase = newphase;
356: switch (phase)
357: {
358: case REQ_DATAOUT : printk("SCSI PHASE = DATA OUT\n"); break;
359: case REQ_DATAIN : printk("SCSI PHASE = DATA IN\n"); break;
360: case REQ_CMDOUT : printk("SCSI PHASE = COMMAND OUT\n"); break;
361: case REQ_STATIN : printk("SCSI PHASE = STATUS IN\n"); break;
362: case REQ_MSGOUT : printk("SCSI PHASE = MESSAGE OUT\n"); break;
363: case REQ_MSGIN : printk("SCSI PHASE = MESSAGE IN\n"); break;
364: default : printk("UNKNOWN PHASE"); st0x_aborted = 1; done = 1;
365: }
366: }
367: #endif
368:
369: switch (status_read & REQ_MASK)
370: {
371: case REQ_DATAOUT :
372:
373: /*
374: We loop as long as we are in a data out phase, there is data to send, and BSY is still
375: active
376: */
377: __asm__ ("
378:
379: /*
380: Local variables :
381: len = ecx
382: data = esi
383: st0x_cr_sr = ebx
384: st0x_dr = edi
385:
386: Test for any data here at all.
387: */
388: movl %0, %%esi /* local value of data */
389: movl %1, %%ecx /* local value of len */
390: orl %%ecx, %%ecx
391: jz 2f
392:
393: cld
394:
395: movl _st0x_cr_sr, %%ebx
396: movl _st0x_dr, %%edi
397:
398: 1: movb (%%ebx), %%al
399: /*
400: Test for BSY
401: */
402:
403: test $1, %%al
404: jz 2f
405:
406: /*
407: Test for data out phase - STATUS & REQ_MASK should be REQ_DATAOUT, which is 0.
408: */
409: test $0xe, %%al
410: jnz 2f
411: /*
412: Test for REQ
413: */
414: test $0x10, %%al
415: jz 1b
416: lodsb
417: movb %%al, (%%edi)
418: loop 1b
419:
420: 2:
421: movl %%esi, %2
422: movl %%ecx, %3
423: ":
424: /* output */
425: "=r" (data), "=r" (len) :
426: /* input */
427: "0" (data), "1" (len) :
428: /* clobbered */
429: "ebx", "ecx", "edi", "esi");
430:
431: break;
432:
433: case REQ_DATAIN :
434: /*
435: We loop as long as we are in a data out phase, there is room to read, and BSY is still
436: active
437: */
438:
439: __asm__ ("
440: /*
441: Local variables :
442: ecx = len
443: edi = data
444: esi = st0x_cr_sr
445: ebx = st0x_dr
446:
447: Test for room to read
448: */
449:
450: movl %0, %%edi /* data */
451: movl %1, %%ecx /* len */
452: orl %%ecx, %%ecx
453: jz 2f
454:
455: cld
456: movl _st0x_cr_sr, %%esi
457: movl _st0x_dr, %%ebx
458:
459: 1: movb (%%esi), %%al
460: /*
461: Test for BSY
462: */
463:
464: test $1, %%al
465: jz 2f
466:
467: /*
468: Test for data in phase - STATUS & REQ_MASK should be REQ_DATAIN, = STAT_IO, which is 4.
469: */
470: movb $0xe, %%ah
471: andb %%al, %%ah
472: cmpb $0x04, %%ah
473: jne 2f
474:
475: /*
476: Test for REQ
477: */
478: test $0x10, %%al
479: jz 1b
480:
481: movb (%%ebx), %%al
482: stosb
483: loop 1b
484:
485: 2: movl %%edi, %2 /* data */
486: movl %%ecx, %3 /* len */
487: ":
488: /* output */
489: "=r" (data), "=r" (len) :
490: /* input */
491: "0" (data), "1" (len) :
492: /* clobbered */
493: "ebx", "ecx", "edi", "esi");
494: break;
495:
496: case REQ_CMDOUT :
497: while (((status_read = STATUS) & STAT_BSY) && ((status_read & REQ_MASK) ==
498: REQ_CMDOUT))
499: DATA = *(unsigned char *) cmnd ++;
500: break;
501:
502: case REQ_STATIN :
503: status = DATA;
504: break;
505:
506: case REQ_MSGOUT :
507: DATA = MESSAGE_REJECT;
508: break;
509:
510: case REQ_MSGIN :
511: if ((message = DATA) == COMMAND_COMPLETE)
512: done=1;
513:
514: break;
515:
516: default : printk("UNKNOWN PHASE"); st0x_aborted = DID_ERROR;
517: }
518: }
519:
520: }
521:
522: #if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT))
523: printk("Transfered %d bytes, allowed %d additional bytes\n", (bufflen - len), len);
524: #endif
525:
526: #if (DEBUG & PHASE_EXIT)
527: printk("Buffer : \n");
528: for (i = 0; i < 20; ++i)
529: printk ("%02x ", ((unsigned char *) buff)[i]);
530: printk("\n");
531: printk("Status = %02x, message = %02x\n", status, message);
532: #endif
533:
534:
535: if (st0x_aborted)
536: {
537: if (STATUS & STAT_BSY)
538: {
539: seagate_st0x_reset();
540: st0x_aborted = DID_RESET;
541: }
542: abort_confirm = 1;
543: }
544:
545: CONTROL = BASE_CMD;
546:
547: #if (DEBUG & PHASE_EXIT)
548: __asm__("
549: mov 4(%%ebp), %%eax
550: ":"=a" (retaddr):);
551:
552: printk("Exiting seagate_st0x_command() - return address is %08x \n", retaddr);
553: if (retaddr != realretaddr)
554: panic ("Corrupted stack : return address on entry != return address on exit.\n");
555:
556: #endif
557:
558: return retcode (st0x_aborted);
559: }
560:
561: int seagate_st0x_abort (int code)
562: {
563: if (code)
564: st0x_aborted = code;
565: else
566: st0x_aborted = DID_ABORT;
567:
568: return 0;
569: }
570:
571: /*
572: the seagate_st0x_reset function resets the SCSI bus
573: */
574:
575: int seagate_st0x_reset (void)
576: {
577: unsigned clock;
578: /*
579: No timeouts - this command is going to fail because
580: it was reset.
581: */
582:
583: #ifdef DEBUG
584: printk("In seagate_st0x_reset()\n");
585: #endif
586:
587:
588: /* assert RESET signal on SCSI bus. */
589:
590: CONTROL = BASE_CMD | CMD_RST;
591: clock=jiffies+2;
592:
593:
594: /* Wait. */
595:
596: while (jiffies < clock);
597:
598: CONTROL = BASE_CMD;
599:
600: st0x_aborted = DID_RESET;
601:
602: #ifdef DEBUG
603: printk("SCSI bus reset.\n");
604: #endif
605: return 0;
606: }
607: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.