This source file includes following definitions.
- inw
- outw
- in2000_test_port
- in2000_txcnt
- in2000_fifo_out
- in2000_fifo_in
- in2000_intr_handle
- in2000_queuecommand
- internal_done
- in2000_command
- in2000_detect
- in2000_abort
- delay
- in2000_reset
- in2000_biosparam
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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 "../block/blk.h"
71 #include "scsi.h"
72 #include "hosts.h"
73 #include "sd.h"
74
75 #include "in2000.h"
76
77
78
79
80 #ifdef DEBUG
81 #define DEB(x) x
82 #else
83 #define DEB(x)
84 #endif
85
86
87 #ifndef inw
88 inline static unsigned short inw( unsigned short port )
89 {
90 unsigned short _v;
91
92 __asm__ volatile ("inw %1,%0"
93 :"=a" (_v):"d" ((unsigned short) port));
94 return _v;
95 }
96 #endif
97
98 #ifndef outw
99 inline static void outw( unsigned short value, unsigned short port )
100 {
101 __asm__ volatile ("outw %0,%1"
102 :
103 :"a" ((unsigned short) value),
104 "d" ((unsigned short) port));
105 }
106 #endif
107
108
109
110 #define port_read(port,buf,nr) \
111 __asm__("cld;rep;insw": :"d" (port),"D" (buf),"c" (nr):"cx","di")
112
113 #define port_write(port,buf,nr) \
114 __asm__("cld;rep;outsw": :"d" (port),"S" (buf),"c" (nr):"cx","si")
115
116 static unsigned int base;
117 static unsigned int ficmsk;
118 static unsigned char irq_level;
119 static int in2000_datalen;
120 static unsigned int in2000_nsegment;
121 static unsigned int in2000_current_segment;
122 static unsigned short *in2000_dataptr;
123 static char in2000_datawrite;
124 static struct scatterlist * in2000_scatter;
125 static Scsi_Cmnd *in2000_SCptr = 0;
126
127 static void (*in2000_done)(Scsi_Cmnd *);
128
129 static int in2000_test_port(int index)
130 {
131 static const int *bios_tab[] = {
132 (int *) 0xc8000, (int *) 0xd0000, (int *) 0xd8000 };
133 int i;
134 char tmp;
135
136 tmp = inb(INFLED);
137
138
139 if ( ((~tmp & 0x3) != index ) || (tmp & 0x80) || !(tmp & 0x4) )
140 return 0;
141 printk("IN-2000 probe got dip setting of %02X\n", tmp);
142 tmp = inb(INVERS);
143
144 for(i=0; i < 3; i++)
145 if(*(bios_tab[i]+0x04) == 0x41564f4e ||
146 *(bios_tab[i]+0xc) == 0x61776c41) {
147 printk("IN-2000 probe found hdw. vers. %02x, BIOS at %06x\n",
148 tmp, (unsigned int)bios_tab[i]);
149 return 1;
150 }
151 printk("in2000 BIOS not found.\n");
152 return 0;
153 }
154
155
156
157
158
159
160 static unsigned in2000_txcnt(void)
161 {
162 unsigned total=0;
163
164 if(inb(INSTAT) & 0x20) return 0xffffff;
165 outb(TXCNTH,INSTAT);
166 total = (inb(INDATA) & 0xff) << 16;
167 outb(TXCNTM,INSTAT);
168 total += (inb(INDATA) & 0xff) << 8;
169 outb(TXCNTL,INSTAT);
170 total += (inb(INDATA) & 0xff);
171 return total;
172 }
173
174
175
176
177
178
179
180
181 static void in2000_fifo_out(void)
182 {
183 unsigned count, infcnt, txcnt;
184
185 infcnt = inb(INFCNT)& 0xfe;
186 do {
187 txcnt = in2000_txcnt();
188
189 count = (infcnt << 3) - 32;
190 if ( count > in2000_datalen )
191 count = in2000_datalen;
192 count >>= 1;
193 #ifdef FAST_FIFO_IO
194 if ( count ) {
195 port_write(INFIFO, in2000_dataptr, count);
196 in2000_datalen -= (count<<1);
197 }
198 #else
199 while ( count-- )
200 {
201 outw(*in2000_dataptr++, INFIFO);
202 in2000_datalen -= 2;
203 }
204 #endif
205 } while((in2000_datalen > 0) && ((infcnt = (inb(INFCNT)) & 0xfe) >= 0x20) );
206
207 if( !in2000_datalen && ++in2000_current_segment < in2000_nsegment)
208 {
209 in2000_scatter++;
210 in2000_datalen = in2000_scatter->length;
211 in2000_dataptr = (unsigned short*)in2000_scatter->address;
212 }
213 if ( in2000_datalen <= 0 )
214 {
215 ficmsk = 0;
216 count = 32;
217 while ( count-- )
218 outw(0, INFIFO);
219 outb(2, ININTR);
220 }
221 }
222
223 static void in2000_fifo_in(void)
224 {
225 unsigned fic, count, count2;
226
227 count = inb(INFCNT) & 0xe1;
228 do{
229 count2 = count;
230 count = (fic = inb(INFCNT)) & 0xe1;
231 } while ( count != count2 );
232 DEB(printk("FIir:%d %02x %08x\n", in2000_datalen,fic,(unsigned int )in2000_dataptr));
233 do {
234 count2 = in2000_txcnt();
235 DEB(printk("FIr:%d %02x %08x %08x\n", in2000_datalen,fic,count2,(unsigned int)in2000_dataptr));
236 if(count2 > 65536) count2 = 0;
237 if(fic > 128) count = 1024;
238 else if(fic > 64) count = 512;
239 else if (fic > 32) count = 256;
240 else if ( count2 < in2000_datalen )
241 count = in2000_datalen - count2;
242 if ( count > in2000_datalen )
243 count2 = in2000_datalen >> 1;
244 else
245 count2 = count >> 1;
246 count >>= 1;
247 count -= count2;
248 #ifdef FAST_FIFO_IO
249 if ( count2 ) {
250 port_read(INFIFO, in2000_dataptr, count2);
251 in2000_datalen -= (count2<<1);
252 }
253 #else
254 while ( count2-- )
255 {
256 *in2000_dataptr++ = inw(INFIFO);
257 in2000_datalen -=2;
258 }
259 #endif
260 } while((in2000_datalen > 0) && (fic = inb(INFCNT)) );
261 DEB(printk("FIer:%d %02x %08x\n", in2000_datalen,fic,(unsigned int )in2000_dataptr));
262
263
264 if( !in2000_datalen && ++in2000_current_segment < in2000_nsegment)
265 {
266 in2000_scatter++;
267 in2000_datalen = in2000_scatter->length;
268 in2000_dataptr = (unsigned short*)in2000_scatter->address;
269 }
270 if ( ! in2000_datalen ){
271 outb(2, ININTR);
272 ficmsk = 0;}
273 }
274
275 static void in2000_intr_handle(int irq, struct pt_regs *regs)
276 {
277 int result=0;
278 unsigned int count,auxstatus,scsistatus,cmdphase,scsibyte;
279 int action=0;
280 Scsi_Cmnd *SCptr;
281
282 DEB(printk("INT:%d %02x %08x\n", in2000_datalen, inb(INFCNT),(unsigned int)in2000_dataptr));
283
284 if (( (ficmsk & (count = inb(INFCNT))) == 0xfe ) ||
285 ( (inb(INSTAT) & 0x8c) == 0x80))
286 {
287 auxstatus = inb(INSTAT);
288 outb(SCSIST,INSTAT);
289 scsistatus = inb(INDATA);
290 outb(TARGETU,INSTAT);
291 scsibyte = inb(INDATA);
292 outb(CMDPHAS,INSTAT);
293 cmdphase = inb(INDATA);
294 DEB(printk("(int2000:%02x %02x %02x %02x %02x)\n",count,auxstatus,
295 scsistatus,cmdphase,scsibyte));
296
297
298 if ( in2000_datalen )
299 {
300 if ( in2000_dataptr == NULL )
301 printk("int2000: dataptr=NULL datalen=%d\n",
302 in2000_datalen);
303 else if ( in2000_datawrite )
304 in2000_fifo_out();
305 else
306 in2000_fifo_in();
307 }
308 if ( (auxstatus & 0x8c) == 0x80 )
309 {
310 outb(2,ININTR);
311 ficmsk = 0;
312 result = DID_OK << 16;
313
314 if ((scsistatus != 0x16) && (scsistatus != 0x85)
315 && (scsistatus != 0x42)){
316
317
318
319
320 ;
321 }
322 switch ( scsistatus & 0xf0 )
323 {
324 case 0x00:
325 action = 3;
326 break;
327 case 0x10:
328 if ( scsistatus & 0x8 )
329 action = 1;
330 break;
331 case 0x20:
332 if ( (scsistatus & 0x8) )
333 action = 1;
334 else if ( (scsistatus & 7) < 2 )
335 action = 2;
336 else
337 result = DID_ABORT << 16;
338 break;
339 case 0x40:
340 if ( scsistatus & 0x8 )
341 action = 1;
342 else if ( (scsistatus & 7) > 2 )
343 action = 2;
344 else
345 result = DID_TIME_OUT << 16;
346 break;
347 case 0x80:
348 if ( scsistatus & 0x8 )
349 action = 1;
350 else
351 action = 2;
352 break;
353 }
354 outb(0,INFLED);
355 switch ( action )
356 {
357 case 0x02:
358 outb(COMMAND,INSTAT);
359 outb(1,INDATA);
360 result = DID_ABORT << 16;
361 case 0x00:
362 if ( ! in2000_SCptr )
363 return;
364 in2000_SCptr->result = result | scsibyte;
365 SCptr = in2000_SCptr;
366 in2000_SCptr = 0;
367 if ( in2000_done )
368 (*in2000_done)(SCptr);
369 break;
370 case 0x01:
371 outb(CMDPHAS,INSTAT);
372 switch ( scsistatus & 7 )
373 {
374 case 0:
375 case 1:
376 case 4:
377 case 5:
378 case 6:
379 case 7:
380 outb(0x41,INDATA);
381 break;
382 case 2:
383 outb(0x30,INDATA);
384 break;
385 case 3:
386 outb(0x45,INDATA);
387 outb(TXCNTH,INSTAT);
388 outb(0,INDATA);
389 outb(0,INDATA);
390 outb(0,INDATA);
391 in2000_datalen = 0;
392 in2000_dataptr = 0;
393 break;
394 }
395 outb(COMMAND,INSTAT);
396 outb(8,INDATA);
397 break;
398 case 0x03:
399 outb(TIMEOUT,INSTAT);
400
401 outb(IN2000_TMOUT,INDATA);
402 outb(CONTROL,INSTAT);
403 outb(0,INDATA);
404 outb(SYNCTXR,INSTAT);
405 outb(0x40,INDATA);
406 break;
407 }
408 }
409 }
410 }
411
412 int in2000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
413 {
414 unchar direction;
415 unchar *cmd = (unchar *) SCpnt->cmnd;
416 unchar target = SCpnt->target;
417 void *buff = SCpnt->request_buffer;
418 unsigned long flags;
419 int bufflen = SCpnt->request_bufflen;
420 int timeout, size, loop;
421 int i;
422
423
424
425
426
427
428
429
430 if ( *cmd == TEST_UNIT_READY )
431 bufflen = 0;
432
433
434
435
436 if (*cmd == READ_10 || *cmd == WRITE_10) {
437 i = xscsi2int((cmd+1));
438 } else if (*cmd == READ_6 || *cmd == WRITE_6) {
439 i = scsi2int((cmd+1));
440 } else {
441 i = -1;
442 }
443 #ifdef DEBUG
444 printk("in2000qcmd: pos %d len %d ", i, bufflen);
445 printk("scsi cmd:");
446 for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);
447 printk("\n");
448 #endif
449 direction = 1;
450 if (*cmd == WRITE_10 || *cmd == WRITE_6)
451 direction = 0;
452 size = SCpnt->cmd_len;
453
454
455
456
457
458
459
460
461
462
463
464
465 if ( in2000_SCptr )
466 {
467 printk("in2000_queue_command waiting for free command block!\n");
468 while ( in2000_SCptr )
469 barrier();
470 }
471 for ( timeout = jiffies + 5; timeout > jiffies; )
472 {
473 if ( ! ( inb(INSTAT) & 0xb0 ) )
474 {
475 timeout = 0;
476 break;
477 }
478 else
479 {
480 inb(INSTAT);
481 outb(SCSIST,INSTAT);
482 inb(INDATA);
483 outb(TARGETU,INSTAT);
484 inb(INDATA);
485 inb(INDATA);
486 }
487 }
488 if ( timeout )
489 {
490 printk("in2000_queue_command timeout!\n");
491 SCpnt->result = DID_TIME_OUT << 16;
492 (*done)(SCpnt);
493 return 1;
494 }
495
496 in2000_nsegment = SCpnt->use_sg;
497 in2000_current_segment = 0;
498 if(SCpnt->use_sg){
499 in2000_scatter = (struct scatterlist *) buff;
500 in2000_datalen = in2000_scatter->length;
501 in2000_dataptr = (unsigned short*)in2000_scatter->address;
502 } else {
503 in2000_scatter = NULL;
504 in2000_datalen = bufflen;
505 in2000_dataptr = (unsigned short*) buff;
506 };
507 in2000_done = done;
508 in2000_SCptr = SCpnt;
509
510
511
512 outb(TOTSECT, INSTAT);
513 for ( loop=0; loop < size; loop++ )
514 outb(cmd[loop],INDATA);
515 outb(TARGETU,INSTAT);
516 outb(SCpnt->lun & 7,INDATA);
517 SCpnt->host_scribble = NULL;
518 outb(TXCNTH,INSTAT);
519 outb(bufflen>>16,INDATA);
520 outb(bufflen>>8,INDATA);
521 outb(bufflen,INDATA);
522 outb(target&7,INDATA);
523
524
525
526 save_flags(flags);
527 cli();
528 outb(0,INFRST);
529 if ( direction == 1 )
530 {
531 in2000_datawrite = 0;
532 outb(0,INFWRT);
533 }
534 else
535 {
536 in2000_datawrite = 1;
537 for ( loop=16; --loop; )
538 {
539 outw(*in2000_dataptr++,INFIFO);
540 if(in2000_datalen > 0) in2000_datalen-=2;
541 }
542 }
543 ficmsk = 0xff;
544
545
546
547 outb(CONTROL,INSTAT);
548 outb(0x4C,INDATA);
549 if ( in2000_datalen )
550 outb(0,ININTR);
551 outb(COMMAND,INSTAT);
552 outb(0,INNLED);
553 outb(8,INDATA);
554 restore_flags(flags);
555 return 0;
556 }
557
558 static volatile int internal_done_flag = 0;
559 static volatile int internal_done_errcode = 0;
560
561 static void internal_done(Scsi_Cmnd * SCpnt)
562 {
563 internal_done_errcode = SCpnt->result;
564 ++internal_done_flag;
565 }
566
567 int in2000_command(Scsi_Cmnd * SCpnt)
568 {
569 in2000_queuecommand(SCpnt, internal_done);
570
571 while (!internal_done_flag);
572 internal_done_flag = 0;
573 return internal_done_errcode;
574 }
575
576 int in2000_detect(Scsi_Host_Template * tpnt)
577 {
578
579 int base_tab[] = { 0x220,0x200,0x110,0x100 };
580 int int_tab[] = { 15,14,11,10 };
581 struct Scsi_Host * shpnt;
582 int loop, tmp;
583
584 DEB(printk("in2000_detect: \n"));
585
586 for ( loop=0; loop < 4; loop++ )
587 {
588 base = base_tab[loop];
589 if ( in2000_test_port(loop)) break;
590 }
591 if ( loop == 4 )
592 return 0;
593
594
595
596 tmp = inb(INFLED);
597
598
599 if ( (tmp & 0x4) == 0 ) {
600 printk("The IN-2000 is not configured for interrupt operation\n");
601 printk("Change the DIP switch settings to enable interrupt operation\n");
602 }
603
604
605 printk("IN-2000 probe found floppy controller on IN-2000 ");
606 if ( (tmp & 0x40) == 0)
607 printk("enabled\n");
608 else
609 printk("disabled\n");
610
611
612 printk("IN-2000 probe found IN-2000 in ");
613 if ( (tmp & 0x20) == 0)
614 printk("synchronous mode\n");
615 else
616 printk("asynchronous mode\n");
617
618 irq_level = int_tab [ ((~inb(INFLED)>>3)&0x3) ];
619
620 printk("Configuring IN2000 at IO:%x, IRQ %d"
621 #ifdef FAST_FIFO_IO
622 " (using fast FIFO I/O code)"
623 #endif
624 "\n",base, irq_level);
625
626 outb(2,ININTR);
627 if (request_irq(irq_level,in2000_intr_handle, 0, "in2000"))
628 {
629 printk("in2000_detect: Unable to allocate IRQ.\n");
630 return 0;
631 }
632 outb(0,INFWRT);
633 outb(SCSIST,INSTAT);
634 inb(INDATA);
635 outb(OWNID,INSTAT);
636 outb(0x7,INDATA);
637 outb(COMMAND,INSTAT);
638 outb(0,INDATA);
639 shpnt = scsi_register(tpnt, 0);
640
641 shpnt->io_port = base;
642 shpnt->n_io_port = 12;
643 shpnt->irq = irq_level;
644 request_region(base, 12,"in2000");
645 return 1;
646 }
647
648 int in2000_abort(Scsi_Cmnd * SCpnt)
649 {
650 DEB(printk("in2000_abort\n"));
651
652
653
654 outb(COMMAND,INSTAT);
655 outb(1,INDATA);
656 return 0;
657 }
658
659 static inline void delay( unsigned how_long )
660 {
661 unsigned long time = jiffies + how_long;
662 while (jiffies < time) ;
663 }
664
665 int in2000_reset(Scsi_Cmnd * SCpnt)
666 {
667 DEB(printk("in2000_reset called\n"));
668
669
670
671 outb(0,INFWRT);
672 outb(SCSIST,INSTAT);
673 inb(INDATA);
674 outb(OWNID,INSTAT);
675 outb(0x7,INDATA);
676 outb(COMMAND,INSTAT);
677 outb(0,INDATA);
678 delay(2);
679 #ifdef SCSI_RESET_PENDING
680 return SCSI_RESET_PENDING;
681 #else
682 if(SCpnt) SCpnt->flags |= NEEDS_JUMPSTART;
683 return 0;
684 #endif
685 }
686
687 int in2000_biosparam(Disk * disk, int dev, int* iinfo)
688 {
689 int size = disk->capacity;
690 DEB(printk("in2000_biosparam\n"));
691 iinfo[0] = 64;
692 iinfo[1] = 32;
693 iinfo[2] = size >> 11;
694
695
696
697 if (iinfo[2] > 1024) {
698 iinfo[0] = 64;
699 iinfo[1] = 63;
700 iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]);
701 }
702 if (iinfo[2] > 1024) {
703 iinfo[0] = 128;
704 iinfo[1] = 63;
705 iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]);
706 }
707 if (iinfo[2] > 1024) {
708 iinfo[0] = 255;
709 iinfo[1] = 63;
710 iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]);
711 if (iinfo[2] > 1023)
712 iinfo[2] = 1023;
713 }
714 return 0;
715 }
716
717 #ifdef MODULE
718
719 Scsi_Host_Template driver_template = IN2000;
720
721 #include "scsi_module.c"
722 #endif
723