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