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 <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 
  84 
  85 
  86 #ifdef DEBUG
  87 #define DEB(x) x
  88 #else
  89 #define DEB(x)
  90 #endif
  91 
  92 
  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                         : 
 109                         :"a" ((unsigned short) value),
 110                         "d" ((unsigned short) port));
 111 }
 112 #endif
 113 
 114 
 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         
 144         
 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 
 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 
 164 
 165 
 166 static unsigned in2000_txcnt(void)
     
 167 {
 168     unsigned total=0;
 169 
 170     if(inb(INSTAT) & 0x20) return 0xffffff;     
 171     outb(TXCNTH,INSTAT);        
 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 
 182 
 183 
 184 
 185 
 186 
 187 static void in2000_fifo_out(void)       
     
 188 {
 189     unsigned count, infcnt, txcnt;
 190 
 191     infcnt = inb(INFCNT)& 0xfe; 
 192     do {
 193         txcnt = in2000_txcnt();
 194 
 195         count = (infcnt << 3) - 32;     
 196         if ( count > in2000_datalen )
 197             count = in2000_datalen;     
 198         count >>= 1;            
 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     
 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;     
 223         while ( count-- )
 224             outw(0, INFIFO);
 225         outb(2, ININTR); 
 226     }
 227 }
 228 
 229 static void in2000_fifo_in(void)        
     
 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();        
 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 ) 
 247                 count = in2000_datalen - count2;        
 248         if ( count > in2000_datalen )   
 249             count2 = in2000_datalen >> 1;       
 250         else
 251             count2 = count >> 1;
 252         count >>= 1;            
 253         count -= count2;        
 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 
 269   
 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); 
 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         {       
 293         auxstatus = inb(INSTAT);        
 294         outb(SCSIST,INSTAT);
 295         scsistatus = inb(INDATA); 
 296         outb(TARGETU,INSTAT);   
 297         scsibyte = inb(INDATA); 
 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         
 304         if ( in2000_datalen )   
 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             {   
 316             outb(2,ININTR);     
 317             ficmsk = 0;
 318             result = DID_OK << 16;
 319             
 320             if ((scsistatus != 0x16) && (scsistatus != 0x85)
 321                 && (scsistatus != 0x42)){
 322 
 323 
 324 
 325 
 326                 ;
 327             }
 328                 switch ( scsistatus & 0xf0 )
 329                     {
 330                     case        0x00:   
 331                         action = 3;
 332                         break;
 333                     case        0x10:   
 334                         if ( scsistatus & 0x8 )
 335                             action = 1;
 336                         break;
 337                     case        0x20:   
 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:   
 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:   
 354                         if ( scsistatus & 0x8 )
 355                             action = 1;
 356                         else
 357                             action = 2;
 358                         break;
 359                     }           
 360                 outb(0,INFLED);
 361                 switch ( action )
 362                     {
 363                     case        0x02:   
 364                         outb(COMMAND,INSTAT);
 365                         outb(1,INDATA);         
 366                         result = DID_ABORT << 16;
 367                     case        0x00:   
 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:   
 377                         outb(CMDPHAS,INSTAT);
 378                         switch ( scsistatus & 7 )
 379                             {
 380                             case        0:      
 381                             case        1:      
 382                             case        4:      
 383                             case        5:      
 384                             case        6:      
 385                             case        7:      
 386                                 outb(0x41,INDATA); 
 387                                 break;
 388                             case        2:      
 389                                 outb(0x30,INDATA); 
 390                                 break;
 391                             case        3:      
 392                                 outb(0x45,INDATA); 
 393                                 outb(TXCNTH,INSTAT); 
 394                                 outb(0,INDATA);
 395                                 outb(0,INDATA);
 396                                 outb(0,INDATA);
 397                                 in2000_datalen = 0;
 398                                 in2000_dataptr = 0;
 399                                 break;
 400                             }   
 401                         outb(COMMAND,INSTAT);
 402                         outb(8,INDATA);  
 403                         break;
 404                     case        0x03:   
 405                         outb(TIMEOUT,INSTAT);   
 406                                                 
 407                         outb(IN2000_TMOUT,INDATA); 
 408                         outb(CONTROL,INSTAT);
 409                         outb(0,INDATA);
 410                         outb(SYNCTXR,INSTAT);
 411                         outb(0x40,INDATA);      
 412                         break;
 413                     }           
 414             }                   
 415         }                       
 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 
 431 
 432 
 433 
 434 
 435 
 436     if ( *cmd == TEST_UNIT_READY )
 437         bufflen = 0;
 438 
 439     
 440 
 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;      
 456     if (*cmd == WRITE_10 || *cmd == WRITE_6)
 457         direction = 0;
 458     size = SCpnt->cmd_len;       
 459     
 460 
 461 
 462 
 463 
 464 
 465 
 466 
 467 
 468 
 469 
 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);       
 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     
 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 
 517 
 518     outb(TOTSECT, INSTAT);      
 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);        
 525     outb(bufflen>>16,INDATA);
 526     outb(bufflen>>8,INDATA);
 527     outb(bufflen,INDATA);
 528     outb(target&7,INDATA);
 529     
 530 
 531 
 532     save_flags(flags);
 533     cli();              
 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; ) 
 544             {
 545                 outw(*in2000_dataptr++,INFIFO);
 546                 if(in2000_datalen > 0) in2000_datalen-=2;
 547             }
 548     }
 549     ficmsk = 0xff;
 550     
 551 
 552 
 553     outb(CONTROL,INSTAT);       
 554     outb(0x4C,INDATA);
 555     if ( in2000_datalen )               
 556         outb(0,ININTR);         
 557     outb(COMMAND,INSTAT);
 558     outb(0,INNLED);
 559     outb(8,INDATA);             
 560     restore_flags(flags);                       
 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 
 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   
 603 
 604   tmp = inb(INFLED);
 605 
 606   
 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   
 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   
 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);     
 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);     
 641     outb(SCSIST,INSTAT);
 642     inb(INDATA);        
 643     outb(OWNID,INSTAT);
 644     outb(0x7,INDATA);   
 645     outb(COMMAND,INSTAT);
 646     outb(0,INDATA);     
 647     shpnt = scsi_register(tpnt, 0);
 648     
 649     shpnt->io_port = base;
 650     shpnt->n_io_port = 12;
 651     shpnt->irq = irq_level;
 652     request_region(base, 12,"in2000");  
 653     return 1;
 654 }
 655 
 656 int in2000_abort(Scsi_Cmnd * SCpnt)
     
 657 {
 658     DEB(printk("in2000_abort\n"));
 659     
 660 
 661 
 662     outb(COMMAND,INSTAT);
 663     outb(1,INDATA);     
 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 
 678 
 679     outb(0,INFWRT);     
 680     outb(SCSIST,INSTAT);
 681     inb(INDATA);
 682     outb(OWNID,INSTAT);
 683     outb(0x7,INDATA);   
 684     outb(COMMAND,INSTAT);
 685     outb(0,INDATA);     
 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 
 703 
 704 
 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 
 727 Scsi_Host_Template driver_template = IN2000;
 728 
 729 #include "scsi_module.c"
 730 #endif
 731