|
|
1.1 root 1: /*
2: * This file is in2000.c, written and
3: * Copyright (C) 1993 Brad McLean
4: * Last edit 1/19/95 TZ
5: * Disclaimer:
6: * Note: This is ugly. I know it, I wrote it, but my whole
7: * focus was on getting the damn thing up and out quickly.
8: * Future stuff that would be nice: Command chaining, and
9: * a local queue of commands would speed stuff up considerably.
10: * Disconnection needs some supporting code. All of this
11: * is beyond the scope of what I wanted to address, but if you
12: * have time and patience, more power to you.
13: * Also, there are some constants scattered throughout that
14: * should have defines, and I should have built functions to
15: * address the registers on the WD chip.
16: * Oh well, I'm out of time for this project.
17: * The one good thing to be said is that you can use the card.
18: */
19:
20: /*
21: * This module was updated by Shaun Savage first on 5-13-93
22: * At that time the write was fixed, irq detection, and some
23: * timing stuff. since that time other problems were fixed.
24: * On 7-20-93 this file was updated for patch level 11
25: * There are still problems with it but it work on 95% of
26: * the machines. There are still problems with it working with
27: * IDE drives, as swap drive and HD that support reselection.
28: * But for most people it will work.
29: */
30: /* More changes by Bill Earnest, [email protected]
31: * through 4/07/94. Includes rewrites of FIFO routines,
32: * length-limited commands to make swap partitions work.
33: * Merged the changes released by Larry Doolittle, based on input
34: * from Jon Luckey, Roger Sunshine, John Shifflett. The FAST_FIFO
35: * doesn't work for me. Scatter-gather code from Eric. The change to
36: * an IF stmt. in the interrupt routine finally made it stable.
37: * Limiting swap request size patch to ll_rw_blk.c not needed now.
38: * Please ignore the clutter of debug stmts., pretty can come later.
39: */
40: /* Merged code from Matt Postiff improving the auto-sense validation
41: * for all I/O addresses. Some reports of problems still come in, but
42: * have been unable to reproduce or localize the cause. Some are from
43: * LUN > 0 problems, but that is not host specific. Now 6/6/94.
44: */
45: /* Changes for 1.1.28 kernel made 7/19/94, code not affected. (WDE)
46: */
47: /* Changes for 1.1.43+ kernels made 8/25/94, code added to check for
48: * new BIOS version, derived by [email protected]. (WDE)
49: *
50: * 1/7/95 Fix from Peter Lu ([email protected]) for datalen vs. dataptr
51: * logic, much more stable under load.
52: *
53: * 1/19/95 ([email protected]) Added module and biosparam support for
54: * larger SCSI hard drives (untested).
55: */
56:
57: #ifdef MODULE
58: #include <linux/module.h>
59: #endif
60:
61: #include <linux/kernel.h>
62: #include <linux/head.h>
63: #include <linux/types.h>
64: #include <linux/string.h>
65: #include <linux/sched.h>
66: #include <linux/proc_fs.h>
67: #include <asm/dma.h>
68: #include <asm/system.h>
69: #include <asm/io.h>
70: #include <linux/blk.h>
71: #include "scsi.h"
72: #include "hosts.h"
73: #include "sd.h"
74:
75: #include "in2000.h"
76: #include<linux/stat.h>
77:
78: struct proc_dir_entry proc_scsi_in2000 = {
79: PROC_SCSI_IN2000, 6, "in2000",
80: S_IFDIR | S_IRUGO | S_IXUGO, 2
81: };
82:
83: /*#define FAST_FIFO_IO*/
84:
85: /*#define DEBUG*/
86: #ifdef DEBUG
87: #define DEB(x) x
88: #else
89: #define DEB(x)
90: #endif
91:
92: /* These functions are based on include/asm/io.h */
93: #ifndef inw
94: inline static unsigned short inw( unsigned short port )
95: {
96: unsigned short _v;
97:
98: __asm__ volatile ("inw %1,%0"
99: :"=a" (_v):"d" ((unsigned short) port));
100: return _v;
101: }
102: #endif
103:
104: #ifndef outw
105: inline static void outw( unsigned short value, unsigned short port )
106: {
107: __asm__ volatile ("outw %0,%1"
108: : /* no outputs */
109: :"a" ((unsigned short) value),
110: "d" ((unsigned short) port));
111: }
112: #endif
113:
114: /* These functions are lifted from drivers/block/hd.c */
115:
116: #define port_read(port,buf,nr) \
117: __asm__("cld;rep;insw": :"d" (port),"D" (buf),"c" (nr):"cx","di")
118:
119: #define port_write(port,buf,nr) \
120: __asm__("cld;rep;outsw": :"d" (port),"S" (buf),"c" (nr):"cx","si")
121:
122: static unsigned int base;
123: static unsigned int ficmsk;
124: static unsigned char irq_level;
125: static int in2000_datalen;
126: static unsigned int in2000_nsegment;
127: static unsigned int in2000_current_segment;
128: static unsigned short *in2000_dataptr;
129: static char in2000_datawrite;
130: static struct scatterlist * in2000_scatter;
131: static Scsi_Cmnd *in2000_SCptr = 0;
132:
133: static void (*in2000_done)(Scsi_Cmnd *);
134:
135: static int in2000_test_port(int index)
136: {
137: static const int *bios_tab[] = {
138: (int *) 0xc8000, (int *) 0xd0000, (int *) 0xd8000 };
139: int i;
140: char tmp;
141:
142: tmp = inb(INFLED);
143: /* First, see if the DIP switch values are valid */
144: /* The test of B7 may fail on some early boards, mine works. */
145: if ( ((~tmp & 0x3) != index ) || (tmp & 0x80) || !(tmp & 0x4) )
146: return 0;
147: printk("IN-2000 probe got dip setting of %02X\n", tmp);
148: tmp = inb(INVERS);
149: /* Add some extra sanity checks here */
150: for(i=0; i < 3; i++)
151: if(*(bios_tab[i]+0x04) == 0x41564f4e ||
152: *(bios_tab[i]+0xc) == 0x61776c41) {
153: printk("IN-2000 probe found hdw. vers. %02x, BIOS at %06x\n",
154: tmp, (unsigned int)bios_tab[i]);
155: return 1;
156: }
157: printk("in2000 BIOS not found.\n");
158: return 0;
159: }
160:
161:
162: /*
163: * retrieve the current transaction counter from the WD
164: */
165:
166: static unsigned in2000_txcnt(void)
167: {
168: unsigned total=0;
169:
170: if(inb(INSTAT) & 0x20) return 0xffffff; /* not readable now */
171: outb(TXCNTH,INSTAT); /* then autoincrement */
172: total = (inb(INDATA) & 0xff) << 16;
173: outb(TXCNTM,INSTAT);
174: total += (inb(INDATA) & 0xff) << 8;
175: outb(TXCNTL,INSTAT);
176: total += (inb(INDATA) & 0xff);
177: return total;
178: }
179:
180: /*
181: * Note: the FIFO is screwy, and has a counter granularity of 16 bytes, so
182: * we have to reconcile the FIFO counter, the transaction byte count from the
183: * WD chip, and of course, our desired transaction size. It may look strange,
184: * and could probably use improvement, but it works, for now.
185: */
186:
187: static void in2000_fifo_out(void) /* uses FIFOCNTR */
188: {
189: unsigned count, infcnt, txcnt;
190:
191: infcnt = inb(INFCNT)& 0xfe; /* FIFO counter */
192: do {
193: txcnt = in2000_txcnt();
194: /*DEB(printk("FIw:%d %02x %d\n", in2000_datalen, infcnt, txcnt));*/
195: count = (infcnt << 3) - 32; /* don't fill completely */
196: if ( count > in2000_datalen )
197: count = in2000_datalen; /* limit to actual data on hand */
198: count >>= 1; /* Words, not bytes */
199: #ifdef FAST_FIFO_IO
200: if ( count ) {
201: port_write(INFIFO, in2000_dataptr, count);
202: in2000_datalen -= (count<<1);
203: }
204: #else
205: while ( count-- )
206: {
207: outw(*in2000_dataptr++, INFIFO);
208: in2000_datalen -= 2;
209: }
210: #endif
211: } while((in2000_datalen > 0) && ((infcnt = (inb(INFCNT)) & 0xfe) >= 0x20) );
212: /* If scatter-gather, go on to next segment */
213: if( !in2000_datalen && ++in2000_current_segment < in2000_nsegment)
214: {
215: in2000_scatter++;
216: in2000_datalen = in2000_scatter->length;
217: in2000_dataptr = (unsigned short*)in2000_scatter->address;
218: }
219: if ( in2000_datalen <= 0 )
220: {
221: ficmsk = 0;
222: count = 32; /* Always says to use this much flush */
223: while ( count-- )
224: outw(0, INFIFO);
225: outb(2, ININTR); /* Mask FIFO Interrupts when done */
226: }
227: }
228:
229: static void in2000_fifo_in(void) /* uses FIFOCNTR */
230: {
231: unsigned fic, count, count2;
232:
233: count = inb(INFCNT) & 0xe1;
234: do{
235: count2 = count;
236: count = (fic = inb(INFCNT)) & 0xe1;
237: } while ( count != count2 );
238: DEB(printk("FIir:%d %02x %08x\n", in2000_datalen,fic,(unsigned int )in2000_dataptr));
239: do {
240: count2 = in2000_txcnt(); /* bytes yet to come over SCSI bus */
241: DEB(printk("FIr:%d %02x %08x %08x\n", in2000_datalen,fic,count2,(unsigned int)in2000_dataptr));
242: if(count2 > 65536) count2 = 0;
243: if(fic > 128) count = 1024;
244: else if(fic > 64) count = 512;
245: else if (fic > 32) count = 256;
246: else if ( count2 < in2000_datalen ) /* if drive has < what we want */
247: count = in2000_datalen - count2; /* FIFO has the rest */
248: if ( count > in2000_datalen ) /* count2 is lesser of FIFO & rqst */
249: count2 = in2000_datalen >> 1; /* converted to word count */
250: else
251: count2 = count >> 1;
252: count >>= 1; /* also to words */
253: count -= count2; /* extra left over in FIFO */
254: #ifdef FAST_FIFO_IO
255: if ( count2 ) {
256: port_read(INFIFO, in2000_dataptr, count2);
257: in2000_datalen -= (count2<<1);
258: }
259: #else
260: while ( count2-- )
261: {
262: *in2000_dataptr++ = inw(INFIFO);
263: in2000_datalen -=2;
264: }
265: #endif
266: } while((in2000_datalen > 0) && (fic = inb(INFCNT)) );
267: DEB(printk("FIer:%d %02x %08x\n", in2000_datalen,fic,(unsigned int )in2000_dataptr));
268: /* while ( count-- )
269: inw(INFIFO);*/ /* Throw away some extra stuff */
270: if( !in2000_datalen && ++in2000_current_segment < in2000_nsegment)
271: {
272: in2000_scatter++;
273: in2000_datalen = in2000_scatter->length;
274: in2000_dataptr = (unsigned short*)in2000_scatter->address;
275: }
276: if ( ! in2000_datalen ){
277: outb(2, ININTR); /* Mask FIFO Interrupts when done */
278: ficmsk = 0;}
279: }
280:
281: static void in2000_intr_handle(int irq, struct pt_regs *regs)
282: {
283: int result=0;
284: unsigned int count,auxstatus,scsistatus,cmdphase,scsibyte;
285: int action=0;
286: Scsi_Cmnd *SCptr;
287:
288: DEB(printk("INT:%d %02x %08x\n", in2000_datalen, inb(INFCNT),(unsigned int)in2000_dataptr));
289:
290: if (( (ficmsk & (count = inb(INFCNT))) == 0xfe ) ||
291: ( (inb(INSTAT) & 0x8c) == 0x80))
292: { /* FIFO interrupt or WD interrupt */
293: auxstatus = inb(INSTAT); /* need to save now */
294: outb(SCSIST,INSTAT);
295: scsistatus = inb(INDATA); /* This clears the WD intrpt bit */
296: outb(TARGETU,INSTAT); /* then autoincrement */
297: scsibyte = inb(INDATA); /* Get the scsi status byte */
298: outb(CMDPHAS,INSTAT);
299: cmdphase = inb(INDATA);
300: DEB(printk("(int2000:%02x %02x %02x %02x %02x)\n",count,auxstatus,
301: scsistatus,cmdphase,scsibyte));
302:
303: /* Why do we assume that we need to send more data here??? ERY */
304: if ( in2000_datalen ) /* data xfer pending */
305: {
306: if ( in2000_dataptr == NULL )
307: printk("int2000: dataptr=NULL datalen=%d\n",
308: in2000_datalen);
309: else if ( in2000_datawrite )
310: in2000_fifo_out();
311: else
312: in2000_fifo_in();
313: }
314: if ( (auxstatus & 0x8c) == 0x80 )
315: { /* There is a WD Chip interrupt & register read good */
316: outb(2,ININTR); /* Disable fifo interrupts */
317: ficmsk = 0;
318: result = DID_OK << 16;
319: /* 16=Select & transfer complete, 85=got disconnect */
320: if ((scsistatus != 0x16) && (scsistatus != 0x85)
321: && (scsistatus != 0x42)){
322: /* printk("(WDi2000:%02x %02x %02x %02x %02x)\n",count,auxstatus,
323: scsistatus,cmdphase,scsibyte);*/
324: /* printk("QDAT:%d %08x %02x\n",
325: in2000_datalen,(unsigned int)in2000_dataptr,ficmsk);*/
326: ;
327: }
328: switch ( scsistatus & 0xf0 )
329: {
330: case 0x00: /* Card Reset Completed */
331: action = 3;
332: break;
333: case 0x10: /* Successful Command Completion */
334: if ( scsistatus & 0x8 )
335: action = 1;
336: break;
337: case 0x20: /* Command Paused or Aborted */
338: if ( (scsistatus & 0x8) )
339: action = 1;
340: else if ( (scsistatus & 7) < 2 )
341: action = 2;
342: else
343: result = DID_ABORT << 16;
344: break;
345: case 0x40: /* Terminated early */
346: if ( scsistatus & 0x8 )
347: action = 1;
348: else if ( (scsistatus & 7) > 2 )
349: action = 2;
350: else
351: result = DID_TIME_OUT << 16;
352: break;
353: case 0x80: /* Service Required from SCSI bus */
354: if ( scsistatus & 0x8 )
355: action = 1;
356: else
357: action = 2;
358: break;
359: } /* end switch(scsistatus) */
360: outb(0,INFLED);
361: switch ( action )
362: {
363: case 0x02: /* Issue an abort */
364: outb(COMMAND,INSTAT);
365: outb(1,INDATA); /* ABORT COMMAND */
366: result = DID_ABORT << 16;
367: case 0x00: /* Basically all done */
368: if ( ! in2000_SCptr )
369: return;
370: in2000_SCptr->result = result | scsibyte;
371: SCptr = in2000_SCptr;
372: in2000_SCptr = 0;
373: if ( in2000_done )
374: (*in2000_done)(SCptr);
375: break;
376: case 0x01: /* We need to reissue a command */
377: outb(CMDPHAS,INSTAT);
378: switch ( scsistatus & 7 )
379: {
380: case 0: /* Data out phase */
381: case 1: /* Data in phase */
382: case 4: /* Unspec info out phase */
383: case 5: /* Unspec info in phase */
384: case 6: /* Message in phase */
385: case 7: /* Message in phase */
386: outb(0x41,INDATA); /* rdy to disconn */
387: break;
388: case 2: /* command phase */
389: outb(0x30,INDATA); /* rdy to send cmd bytes */
390: break;
391: case 3: /* status phase */
392: outb(0x45,INDATA); /* To go to status phase,*/
393: outb(TXCNTH,INSTAT); /* elim. data, autoinc */
394: outb(0,INDATA);
395: outb(0,INDATA);
396: outb(0,INDATA);
397: in2000_datalen = 0;
398: in2000_dataptr = 0;
399: break;
400: } /* end switch(scsistatus) */
401: outb(COMMAND,INSTAT);
402: outb(8,INDATA); /* RESTART THE COMMAND */
403: break;
404: case 0x03: /* Finish up a Card Reset */
405: outb(TIMEOUT,INSTAT); /* I got these values */
406: /* by reverse Engineering */
407: outb(IN2000_TMOUT,INDATA); /* the Always' bios. */
408: outb(CONTROL,INSTAT);
409: outb(0,INDATA);
410: outb(SYNCTXR,INSTAT);
411: outb(0x40,INDATA); /* async, 4 cyc xfer per. */
412: break;
413: } /* end switch(action) */
414: } /* end if auxstatus for WD int */
415: } /* end while intrpt active */
416: }
417:
418: int in2000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
419: {
420: unchar direction;
421: unchar *cmd = (unchar *) SCpnt->cmnd;
422: unchar target = SCpnt->target;
423: void *buff = SCpnt->request_buffer;
424: unsigned long flags;
425: int bufflen = SCpnt->request_bufflen;
426: int timeout, size, loop;
427: int i;
428:
429: /*
430: * This SCSI command has no data phase, but unfortunately the mid-level
431: * SCSI drivers ask for 256 bytes of data xfer. Our card hangs if you
432: * do this, so we protect against it here. It would be nice if the mid-
433: * level could be changed, but who knows if that would break other host
434: * adapter drivers.
435: */
436: if ( *cmd == TEST_UNIT_READY )
437: bufflen = 0;
438:
439: /*
440: * What it looks like. Boy did I get tired of reading its output.
441: */
442: if (*cmd == READ_10 || *cmd == WRITE_10) {
443: i = xscsi2int((cmd+1));
444: } else if (*cmd == READ_6 || *cmd == WRITE_6) {
445: i = scsi2int((cmd+1));
446: } else {
447: i = -1;
448: }
449: #ifdef DEBUG
450: printk("in2000qcmd: pos %d len %d ", i, bufflen);
451: printk("scsi cmd:");
452: for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);
453: printk("\n");
454: #endif
455: direction = 1; /* assume for most commands */
456: if (*cmd == WRITE_10 || *cmd == WRITE_6)
457: direction = 0;
458: size = SCpnt->cmd_len; /* CDB length */
459: /*
460: * Setup our current pointers
461: * This is where you would allocate a control structure in a queue,
462: * If you were going to upgrade this to do multiple issue.
463: * Note that datalen and dataptr exist because we can change the
464: * values during the course of the operation, while managing the
465: * FIFO.
466: * Note the nasty little first clause. In theory, the mid-level
467: * drivers should never hand us more than one command at a time,
468: * but just in case someone gets cute in configuring the driver,
469: * we'll protect them, although not very politely.
470: */
471: if ( in2000_SCptr )
472: {
473: printk("in2000_queue_command waiting for free command block!\n");
474: while ( in2000_SCptr )
475: barrier();
476: }
477: for ( timeout = jiffies + 5; timeout > jiffies; )
478: {
479: if ( ! ( inb(INSTAT) & 0xb0 ) )
480: {
481: timeout = 0;
482: break;
483: }
484: else
485: {
486: inb(INSTAT);
487: outb(SCSIST,INSTAT);
488: inb(INDATA);
489: outb(TARGETU,INSTAT); /* then autoinc */
490: inb(INDATA);
491: inb(INDATA);
492: }
493: }
494: if ( timeout )
495: {
496: printk("in2000_queue_command timeout!\n");
497: SCpnt->result = DID_TIME_OUT << 16;
498: (*done)(SCpnt);
499: return 1;
500: }
501: /* Added for scatter-gather support */
502: in2000_nsegment = SCpnt->use_sg;
503: in2000_current_segment = 0;
504: if(SCpnt->use_sg){
505: in2000_scatter = (struct scatterlist *) buff;
506: in2000_datalen = in2000_scatter->length;
507: in2000_dataptr = (unsigned short*)in2000_scatter->address;
508: } else {
509: in2000_scatter = NULL;
510: in2000_datalen = bufflen;
511: in2000_dataptr = (unsigned short*) buff;
512: };
513: in2000_done = done;
514: in2000_SCptr = SCpnt;
515: /*
516: * Write the CDB to the card, then the LUN, the length, and the target.
517: */
518: outb(TOTSECT, INSTAT); /* start here then autoincrement */
519: for ( loop=0; loop < size; loop++ )
520: outb(cmd[loop],INDATA);
521: outb(TARGETU,INSTAT);
522: outb(SCpnt->lun & 7,INDATA);
523: SCpnt->host_scribble = NULL;
524: outb(TXCNTH,INSTAT); /* then autoincrement */
525: outb(bufflen>>16,INDATA);
526: outb(bufflen>>8,INDATA);
527: outb(bufflen,INDATA);
528: outb(target&7,INDATA);
529: /*
530: * Set up the FIFO
531: */
532: save_flags(flags);
533: cli(); /* so FIFO init waits till WD set */
534: outb(0,INFRST);
535: if ( direction == 1 )
536: {
537: in2000_datawrite = 0;
538: outb(0,INFWRT);
539: }
540: else
541: {
542: in2000_datawrite = 1;
543: for ( loop=16; --loop; ) /* preload the outgoing fifo */
544: {
545: outw(*in2000_dataptr++,INFIFO);
546: if(in2000_datalen > 0) in2000_datalen-=2;
547: }
548: }
549: ficmsk = 0xff;
550: /*
551: * Start it up
552: */
553: outb(CONTROL,INSTAT); /* WD BUS Mode */
554: outb(0x4C,INDATA);
555: if ( in2000_datalen ) /* if data xfer cmd */
556: outb(0,ININTR); /* Enable FIFO intrpt some boards? */
557: outb(COMMAND,INSTAT);
558: outb(0,INNLED);
559: outb(8,INDATA); /* Select w/ATN & Transfer */
560: restore_flags(flags); /* let the intrpt rip */
561: return 0;
562: }
563:
564: static volatile int internal_done_flag = 0;
565: static volatile int internal_done_errcode = 0;
566:
567: static void internal_done(Scsi_Cmnd * SCpnt)
568: {
569: internal_done_errcode = SCpnt->result;
570: ++internal_done_flag;
571: }
572:
573: int in2000_command(Scsi_Cmnd * SCpnt)
574: {
575: in2000_queuecommand(SCpnt, internal_done);
576:
577: while (!internal_done_flag);
578: internal_done_flag = 0;
579: return internal_done_errcode;
580: }
581:
582: int in2000_detect(Scsi_Host_Template * tpnt)
583: {
584: /* Order chosen to reduce conflicts with some multi-port serial boards */
585: int base_tab[] = { 0x220,0x200,0x110,0x100 };
586: int int_tab[] = { 15,14,11,10 };
587: struct Scsi_Host * shpnt;
588: int loop, tmp;
589:
590: DEB(printk("in2000_detect: \n"));
591:
592: tpnt->proc_dir = &proc_scsi_in2000;
593:
594: for ( loop=0; loop < 4; loop++ )
595: {
596: base = base_tab[loop];
597: if ( in2000_test_port(loop)) break;
598: }
599: if ( loop == 4 )
600: return 0;
601:
602: /* Read the dip switch values again for miscellaneous checking and
603: informative messages */
604: tmp = inb(INFLED);
605:
606: /* Bit 2 tells us if interrupts are disabled */
607: if ( (tmp & 0x4) == 0 ) {
608: printk("The IN-2000 is not configured for interrupt operation\n");
609: printk("Change the DIP switch settings to enable interrupt operation\n");
610: }
611:
612: /* Bit 6 tells us about floppy controller */
613: printk("IN-2000 probe found floppy controller on IN-2000 ");
614: if ( (tmp & 0x40) == 0)
615: printk("enabled\n");
616: else
617: printk("disabled\n");
618:
619: /* Bit 5 tells us about synch/asynch mode */
620: printk("IN-2000 probe found IN-2000 in ");
621: if ( (tmp & 0x20) == 0)
622: printk("synchronous mode\n");
623: else
624: printk("asynchronous mode\n");
625:
626: irq_level = int_tab [ ((~inb(INFLED)>>3)&0x3) ];
627:
628: printk("Configuring IN2000 at IO:%x, IRQ %d"
629: #ifdef FAST_FIFO_IO
630: " (using fast FIFO I/O code)"
631: #endif
632: "\n",base, irq_level);
633:
634: outb(2,ININTR); /* Shut off the FIFO first, so it won't ask for data.*/
635: if (request_irq(irq_level,in2000_intr_handle, 0, "in2000"))
636: {
637: printk("in2000_detect: Unable to allocate IRQ.\n");
638: return 0;
639: }
640: outb(0,INFWRT); /* read mode so WD can intrpt */
641: outb(SCSIST,INSTAT);
642: inb(INDATA); /* free status reg, clear WD intrpt */
643: outb(OWNID,INSTAT);
644: outb(0x7,INDATA); /* we use addr 7 */
645: outb(COMMAND,INSTAT);
646: outb(0,INDATA); /* do chip reset */
647: shpnt = scsi_register(tpnt, 0);
648: /* Set these up so that we can unload the driver properly. */
649: shpnt->io_port = base;
650: shpnt->n_io_port = 12;
651: shpnt->irq = irq_level;
652: request_region(base, 12,"in2000"); /* Prevent other drivers from using this space */
653: return 1;
654: }
655:
656: int in2000_abort(Scsi_Cmnd * SCpnt)
657: {
658: DEB(printk("in2000_abort\n"));
659: /*
660: * Ask no stupid questions, just order the abort.
661: */
662: outb(COMMAND,INSTAT);
663: outb(1,INDATA); /* Abort Command */
664: return 0;
665: }
666:
667: static inline void delay( unsigned how_long )
668: {
669: unsigned long time = jiffies + how_long;
670: while (jiffies < time) ;
671: }
672:
673: int in2000_reset(Scsi_Cmnd * SCpnt)
674: {
675: DEB(printk("in2000_reset called\n"));
676: /*
677: * Note: this is finished off by an incoming interrupt
678: */
679: outb(0,INFWRT); /* read mode so WD can intrpt */
680: outb(SCSIST,INSTAT);
681: inb(INDATA);
682: outb(OWNID,INSTAT);
683: outb(0x7,INDATA); /* ID=7,noadv, no parity, clk div=2 (8-10Mhz clk) */
684: outb(COMMAND,INSTAT);
685: outb(0,INDATA); /* reset WD chip */
686: delay(2);
687: #ifdef SCSI_RESET_PENDING
688: return SCSI_RESET_PENDING;
689: #else
690: if(SCpnt) SCpnt->flags |= NEEDS_JUMPSTART;
691: return 0;
692: #endif
693: }
694:
695: int in2000_biosparam(Disk * disk, kdev_t dev, int* iinfo)
696: {
697: int size = disk->capacity;
698: DEB(printk("in2000_biosparam\n"));
699: iinfo[0] = 64;
700: iinfo[1] = 32;
701: iinfo[2] = size >> 11;
702: /* This should approximate the large drive handling that the DOS ASPI manager
703: uses. Drives very near the boundaries may not be handled correctly (i.e.
704: near 2.0 Gb and 4.0 Gb) */
705: if (iinfo[2] > 1024) {
706: iinfo[0] = 64;
707: iinfo[1] = 63;
708: iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]);
709: }
710: if (iinfo[2] > 1024) {
711: iinfo[0] = 128;
712: iinfo[1] = 63;
713: iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]);
714: }
715: if (iinfo[2] > 1024) {
716: iinfo[0] = 255;
717: iinfo[1] = 63;
718: iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]);
719: if (iinfo[2] > 1023)
720: iinfo[2] = 1023;
721: }
722: return 0;
723: }
724:
725: #ifdef MODULE
726: /* Eventually this will go into an include file, but this will be later */
727: Scsi_Host_Template driver_template = IN2000;
728:
729: #include "scsi_module.c"
730: #endif
731:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.