⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aha152x.c

📁 LINUX 1.0 内核c源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
          current_SC->SCp.phase |= sent_ident;

        if(message==ABORT)
          {
            /* revive abort(); abort() enables interrupts */
            abort_result=0;
            wake_up( &abortion_complete );

            current_SC->SCp.phase = (current_SC->SCp.phase & ~(P_MASK<<16));

            /* exit */
            SETBITS( DMACNTRL0, INTEN );
#if defined(DEBUG_RACE)
            leave_driver("(ABORT) intr");
#endif
            aha152x_done(DID_ABORT<<16);
            return;
          }
      }
      break;

    case P_CMD:                                          /* COMMAND phase */
#if defined(DEBUG_INTR) || defined(DEBUG_CMD) || defined(DEBUG_PHASES)
      printk("COMMAND, ");
#endif
      if( !(current_SC->SCp.sent_command) )
        {
          if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT))
            printk("aha152x: P_CMD: %d(%d) bytes left in FIFO, resetting\n",
                   GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT));

          /* reset fifo and enable writes */
          SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO);
          SETPORT(DMACNTRL0, ENDMA|WRITE_READ);

          /* clear transfer count and scsi fifo */
          SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1 );
          SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1);
  
          /* missing phase raises INTSTAT */
          SETPORT( SIMODE0, 0 );
          SETPORT( SIMODE1, ENPHASEMIS );
  
#if defined(DEBUG_CMD)
          printk("waiting, ");
#endif
          /* wait for FIFO to get empty */
          while( TESTLO ( DMASTAT, DFIFOEMP|INTSTAT ) )
            ;
  
          if( TESTHI( SSTAT1, PHASEMIS ) )
            aha152x_panic("target left COMMAND phase");

#if defined(DEBUG_CMD)
          printk("DFIFOEMP, outsw (%d words), ",
                 COMMAND_SIZE(current_SC->cmnd[0])>>1);
          disp_ports();
#endif
  
          outsw( DATAPORT,
                 &current_SC->cmnd,
                 COMMAND_SIZE(current_SC->cmnd[0])>>1 );

#if defined(DEBUG_CMD)
          printk("FCNT=%d, STCNT=%d, ", GETPORT(FIFOSTAT), GETSTCNT() );
          disp_ports();
#endif

          /* wait for SCSI FIFO to get empty.
             very important to send complete commands. */
          while( TESTLO ( SSTAT2, SEMPTY ) )
            ;

          CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
          /* transfer can be considered ended, when SCSIEN reads back zero */
          while( TESTHI( SXFRCTL0, SCSIEN ) )
            ;

          CLRBITS(DMACNTRL0, ENDMA);

#if defined(DEBUG_CMD) || defined(DEBUG_INTR)
          printk("sent %d/%d command bytes, ", GETSTCNT(),
                 COMMAND_SIZE(current_SC->cmnd[0]));
#endif

        }
      else
        aha152x_panic("Nothing to sent while in COMMAND OUT");
      break;

    case P_MSGI:                                          /* MESSAGE IN phase */
#if defined(DEBUG_INTR) || defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
      printk("MESSAGE IN, ");
#endif
      SETPORT( SXFRCTL0, CH1);

      SETPORT( SIMODE0, 0);
      SETPORT( SIMODE1, ENBUSFREE);
  
      while( phase == P_MSGI ) 
        {
          current_SC->SCp.Message = GETPORT( SCSIBUS );
          switch(current_SC->SCp.Message)
            {
            case DISCONNECT:
#if defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
              printk("target disconnected, ");
#endif
              current_SC->SCp.Message = 0;
              current_SC->SCp.phase   |= disconnected;
              if(!can_disconnect)
                aha152x_panic("target was not allowed to disconnect");
              break;
        
            case COMMAND_COMPLETE:
#if defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
              printk("inbound message ( COMMAND COMPLETE ), ");
#endif
              done++;
              break;

            case MESSAGE_REJECT:
#if defined(DEBUG_MSGI) || defined(DEBUG_TIMING)
              printk("inbound message ( MESSAGE REJECT ), ");
#endif
              break;

            case SAVE_POINTERS:
#if defined(DEBUG_MSGI)
              printk("inbound message ( SAVE DATA POINTERS ), ");
#endif
              break;

            case EXTENDED_MESSAGE:
              { 
                int           i, code;

#if defined(DEBUG_MSGI)
                printk("inbound message ( EXTENDED MESSAGE ), ");
#endif
                make_acklow();
                if(getphase()!=P_MSGI)
                  break;
  
                i=GETPORT(SCSIBUS);

#if defined(DEBUG_MSGI)
                printk("length (%d), ", i);
#endif

#if defined(DEBUG_MSGI)
                printk("code ( ");
#endif

                make_acklow();
                if(getphase()!=P_MSGI)
                  break;

                code = GETPORT(SCSIBUS);

                switch( code )
                  {
                  case 0x00:
#if defined(DEBUG_MSGI)
                    printk("MODIFY DATA POINTER ");
#endif
                    SETPORT(SCSISIG, P_MSGI|ATNO);
                    break;
                  case 0x01:
#if defined(DEBUG_MSGI)
                    printk("SYNCHRONOUS DATA TRANSFER REQUEST ");
#endif
                    SETPORT(SCSISIG, P_MSGI|ATNO);
                    break;
                  case 0x02:
#if defined(DEBUG_MSGI)
                    printk("EXTENDED IDENTIFY ");
#endif
                    break;
                  case 0x03:
#if defined(DEBUG_MSGI)
                    printk("WIDE DATA TRANSFER REQUEST ");
#endif
                    SETPORT(SCSISIG, P_MSGI|ATNO);
                    break;
                  default:
#if defined(DEBUG_MSGI)
                    if( code & 0x80 )
                      printk("reserved (%d) ", code );
                    else
                      printk("vendor specific (%d) ", code);
#endif
                    SETPORT(SCSISIG, P_MSGI|ATNO);
                    break;
                  }
#if defined(DEBUG_MSGI)
                printk(" ), data ( ");
#endif
                while( --i && (make_acklow(), getphase()==P_MSGI))
                  {
#if defined(DEBUG_MSGI)
                    printk("%x ", GETPORT(SCSIBUS) );
#else
                    GETPORT(SCSIBUS);
#endif
                  }
#if defined(DEBUG_MSGI)
                printk(" ), ");
#endif
                /* We reject all extended messages. To do this
                   we just enter MSGO by asserting ATN. Since
                   we have already identified a REJECT message
                   will be sent. */
                SETPORT(SCSISIG, P_MSGI|ATNO);
              }
              break;
       
            default:
              printk("unsupported inbound message %x, ", current_SC->SCp.Message);
              break;

            }

          make_acklow();
          phase=getphase();
        } 

      /* clear SCSI fifo on BUSFREE */
      if(phase==P_BUSFREE)
        SETPORT(SXFRCTL0, CH1|CLRCH1);

      if(current_SC->SCp.phase & disconnected)
        {
          cli();
#if defined(DEBUG_QUEUES)
          printk("d+, ");
#endif
          append_SC( &disconnected_SC, current_SC);
          current_SC = NULL;
          sti();

          SETBITS( SCSISEQ, ENRESELI );

          SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
          SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);

          SETBITS( DMACNTRL0, INTEN );
          return;
        }
      break;

    case P_STATUS:                                         /* STATUS IN phase */
#if defined(DEBUG_STATUS) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
      printk("STATUS, ");
#endif
      SETPORT( SXFRCTL0, CH1);

      SETPORT( SIMODE0, 0 );
      SETPORT( SIMODE1, ENREQINIT );

      if( TESTHI( SSTAT1, PHASEMIS ) )
	printk("aha152x: passing STATUS phase");
	
      current_SC->SCp.Status = GETPORT( SCSIBUS );
      make_acklow();
      getphase();

#if defined(DEBUG_STATUS)
      printk("inbound status ");
      print_status( current_SC->SCp.Status );
      printk(", ");
#endif
      break;

    case P_DATAI:                                            /* DATA IN phase */
      {
        int fifodata, data_count, done;

#if defined(DEBUG_DATAI) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
        printk("DATA IN, ");
#endif

        if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT))
          printk("aha152x: P_DATAI: %d(%d) bytes left in FIFO, resetting\n",
                 GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT));

        /* reset host fifo */
        SETPORT(DMACNTRL0, RSTFIFO);
        SETPORT(DMACNTRL0, RSTFIFO|ENDMA);

        SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN );

        SETPORT( SIMODE0, 0 );
        SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );

        /* done is set when the FIFO is empty after the target left DATA IN */
        done=0;
      
        /* while the target stays in DATA to transfer data */
        while ( !done ) 
          {
#if defined(DEBUG_DATAI)
            printk("expecting data, ");
#endif
            /* wait for PHASEMIS or full FIFO */
            while( TESTLO ( DMASTAT, DFIFOFULL|INTSTAT ) )
              ;

            if( TESTHI( DMASTAT, DFIFOFULL ) )
              fifodata=132;
            else
              {
                /* wait for SCSI fifo to get empty */
                while( TESTLO( SSTAT2, SEMPTY ) )
                  ;

                /* rest of data in FIFO */
                fifodata=GETPORT(FIFOSTAT);
#if defined(DEBUG_DATAI)
                printk("last transfer, ");
#endif
                done=1;
              }
  
#if defined(DEBUG_DATAI)
            printk("fifodata=%d, ", fifodata);
#endif

            while( fifodata && current_SC->SCp.this_residual )
              {
                data_count=fifodata;
  
                /* limit data transfer to size of first sg buffer */
                if (data_count > current_SC->SCp.this_residual)
                  data_count = current_SC->SCp.this_residual;
  
                fifodata -= data_count;

#if defined(DEBUG_DATAI)
                printk("data_count=%d, ", data_count);
#endif
  
                if(data_count == 1)
                  {
                    /* get a single byte in byte mode */
                    SETBITS(DMACNTRL0, _8BIT );
                    *current_SC->SCp.ptr++ = GETPORT( DATAPORT );
                    current_SC->SCp.this_residual--;
                  }
                else
                  {
                    CLRBITS(DMACNTRL0, _8BIT );
                    data_count >>= 1; /* Number of words */
                    insw( DATAPORT, current_SC->SCp.ptr, data_count );
#if defined(DEBUG_DATAI)
/* show what comes with the last transfer */
                    if(done)
                      {
                        int           i;
                        unsigned char *data;

                        printk("data on last transfer (%d bytes: ",
                               2*data_count);
                        data = (unsigned char *) current_SC->SCp.ptr;
                        for( i=0; i<2*data_count; i++)
                          printk("%2x ", *data++);
                        printk("), ");
                      }
#endif
                    current_SC->SCp.ptr           += 2 * data_count;
                    current_SC->SCp.this_residual -= 2 * data_count;
                  }
              
                /* if this buffer is full and there are more buffers left */
                if (!current_SC->SCp.this_residual &&
                     current_SC->SCp.buffers_residual)
                  {
                    /* advance to next buffer */
                    current_SC->SCp.buffers_residual--;
                    current_SC->SCp.buffer++;
                    current_SC->SCp.ptr =
                      current_SC->SCp.buffer->address;
                    current_SC->SCp.this_residual =
                      current_SC->SCp.buffer->length;
                  } 
              }
 
            /* rare (but possible) status bytes (probably also DISCONNECT 
               messages) get transfered in the data phase, so I assume 1
               additional byte is ok */
            if(fifodata>1)
              {
                printk("aha152x: more data than expected (%d bytes)\n",
                       GETPORT(FIFOSTAT));
              }

#if defined(DEBUG_DATAI)
            if(!fifodata)
              printk("fifo empty, ");
            else
              printk("something left in fifo, ");
#endif
          }

#if defined(DEBUG_DATAI)
        if(current_SC->SCp.buffers_residual || current_SC->SCp.this_residual)
          printk("left buffers (buffers=%d, bytes=%d), ",
                 current_SC->SCp.buffers_residual, 
                 current_SC->SCp.this_residual);
#endif
        /* transfer can be considered ended, when SCSIEN reads back zero */
        CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
        while( TESTHI( SXFRCTL0, SCSIEN ) )
          ;
        CLRBITS(DMACNTRL0, ENDMA );

#if defined(DEBUG_DATAI) || defined(DEBUG_INTR)
        printk("got %d bytes, ", GETSTCNT());
#endif

        current_SC->SCp.have_data_in++;
      }
      break;

    case P_DATAO:                                           /* DATA OUT phase */
      {
        int data_count;

#if defined(DEBUG_DATAO) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
        printk("DATA OUT, ");
#endif
#if defined(DEBUG_DATAO)
        printk("got data to send (bytes=%d, buffers=%d), ",
               current_SC->SCp.this_residual,
               current_SC->SCp.buffers_residual );
#endif

        if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT) )
          {
            printk("%d(%d) left in FIFO, ", GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT) );
            aha152x_panic("FIFO should be empty");
          }

        SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO);
        SETPORT(DMACNTRL0, ENDMA|WRITE_READ);

        SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1 );
        SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1);
 
        SETPORT( SIMODE0, 0 );
        SETPORT( SIMODE1, ENPHASEMIS );

        /* while current buffer is not empty or
           there are more buffers to transfer */
        while( TESTLO( SSTAT1, PHASEMIS ) &&
                 (current_SC->SCp.this_residual ||
                  current_SC->SCp.buffers_residual) )
          {
#if defined(DEBUG_DATAO)
            printk("sending data (left: bytes=%d, buffers=%d), waiting, ",
                    current_SC->SCp.this_residual,
                    current_SC->SCp.buffers_residual);
#endif
            /* transfer rest of buffer, but max. 128 byte */
            data_count = current_SC->SCp.this_residual > 128 ?
                         128 : current_SC->SCp.this_residual ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -