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

📄 aha152x.c

📁 LINUX 1.0 内核c源代码
💻 C
📖 第 1 页 / 共 5 页
字号:

       while(disconnected_SC)
         {
           ptr = disconnected_SC;
           disconnected_SC = (Scsi_Cmnd *) ptr->host_scribble;
           ptr->host_scribble = NULL;
           ptr->result = DID_RESET << 16;
           ptr->done(ptr);
         }

       /* RESET OUT */
       SETPORT(SCSISEQ, SCSIRSTO);
       do_pause(5);
       SETPORT(SCSISEQ, 0);
       do_pause(10);

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

       SETPORT( DMACNTRL0, INTEN );
    }

  return 0;
}

/*
 * Return the "logical geometry"
 */
int aha152x_biosparam( int size, int dev, int *info_array )
{
#if defined(DEBUG_RACE)
  enter_driver("biosparam");
#else
#if defined(DEBUG_BIOSPARAM)
  printk("\naha152x: biosparam(), ");
#endif
#endif

#if defined(DEBUG_BIOSPARAM)
  printk("dev=%x, size=%d, ", dev, size);
#endif
  
/* I took this from other SCSI drivers, since it provides
   the correct data for my devices. */
  info_array[0]=64;
  info_array[1]=32;
  info_array[2]=size>>11;

#if defined(DEBUG_BIOSPARAM)
  printk("bios geometry: head=%d, sec=%d, cyl=%d\n",
         info_array[0], info_array[1], info_array[2]);
  printk("WARNING: check, if the bios geometry is correct.\n");
#endif

#if defined(DEBUG_RACE)
  leave_driver("biosparam");
#endif
  return 0;
}

/*
 *  Internal done function
 */
void aha152x_done( int error )
{
  Scsi_Cmnd *done_SC;

#if defined(DEBUG_DONE)
  printk("\naha152x: done(), ");
  disp_ports();
#endif

  if (current_SC)
    {
#if defined(DEBUG_DONE)
      printk("done(%x), ", error);
#endif

      cli();

      done_SC = current_SC;
      current_SC = NULL;

      /* turn led off, when no commands are in the driver */
      commands--;
      if(!commands)
        SETPORT( PORTA, 0 );                                  /* turn led off */

#if defined(DEBUG_QUEUES)
      printk("ok (%d), ", commands);
#endif
      sti();

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

#if defined(DEBUG_PHASES)
      printk("BUS FREE loop, ");
#endif
      while( TESTLO( SSTAT1, BUSFREE ) )
        ;
#if defined(DEBUG_PHASES)
      printk("BUS FREE\n");
#endif

      done_SC->result = error;
      if(done_SC->scsi_done)
        {
#if defined(DEBUG_DONE)
          printk("calling scsi_done, ");
#endif
          done_SC->scsi_done( done_SC );
#if defined(DEBUG_DONE)
          printk("done returned, ");
#endif
        }
      else
        panic( "aha152x: current_SC->scsi_done() == NULL" );
    }
  else
    aha152x_panic( "done() called outside of command" );
}

/*
 * Interrupts handler (main routine of the driver)
 */
void aha152x_intr( int irqno )
{
  int done=0, phase;

#if defined(DEBUG_RACE)
  enter_driver("intr");
#else
#if defined(DEBUG_INTR)
  printk("\naha152x: intr(), ");
#endif
#endif

  /* no more interrupts from the controller, while we busy.
     INTEN has to be restored, when we're ready to leave
     intr(). To avoid race conditions we have to return
     immediately afterwards. */
  CLRBITS( DMACNTRL0, INTEN);
  sti();

  /* disconnected target is trying to reconnect.
     Only possible, if we have disconnected nexuses and
     nothing is occuping the bus.
  */
  if( TESTHI( SSTAT0, SELDI ) &&
      disconnected_SC &&
      ( !current_SC || ( current_SC->SCp.phase & in_selection ) )
    )
    {
      int identify_msg, target, i;

      /* Avoid conflicts when a target reconnects
         while we are trying to connect to another. */
      if(current_SC)
        {
#if defined(DEBUG_QUEUES)
          printk("i+, ");
#endif
          cli();
          append_SC( &issue_SC, current_SC);
          current_SC=NULL;
          sti();
        }

      /* disable sequences */
      SETPORT( SCSISEQ, 0 );
      SETPORT( SSTAT0, CLRSELDI );
      SETPORT( SSTAT1, CLRBUSFREE );

#if defined(DEBUG_QUEUES) || defined(DEBUG_PHASES)
      printk("reselected, ");
#endif

      i = GETPORT(SELID) & ~(1 << this_host);
      target=0;
      if(i)
        for( ; (i & 1)==0; target++, i>>=1)
          ;
      else
        aha152x_panic("reconnecting target unknown");

#if defined(DEBUG_QUEUES)
      printk("SELID=%02x, target=%d, ", GETPORT(SELID), target );
#endif
      SETPORT( SCSIID, (this_host << OID_) | target );
      SETPORT( SCSISEQ, ENRESELI );

      if(TESTLO( SSTAT0, SELDI ))
        aha152x_panic("RESELI failed");

      SETPORT( SCSISIG, P_MSGI );

      /* Get identify message */
      if((i=getphase())!=P_MSGI)
        {
          printk("target doesn't enter MSGI to identify (phase=%02x)\n", i);
          aha152x_panic("unknown lun");
        }
      SETPORT( SCSISEQ, 0 );

      SETPORT( SXFRCTL0, CH1);

      identify_msg = GETPORT(SCSIBUS);

      if(!(identify_msg & IDENTIFY_BASE))
        {
          printk("target=%d, inbound message (%02x) != IDENTIFY\n",
                 target, identify_msg);
          aha152x_panic("unknown lun");
        }

      make_acklow();
      getphase();

#if defined(DEBUG_QUEUES)
      printk("identify=%02x, lun=%d, ", identify_msg, identify_msg & 0x3f );
#endif

      cli();
#if defined(DEBUG_QUEUES)
      printk("d-, ");
#endif
      current_SC = remove_SC( &disconnected_SC,
                              target,
                              identify_msg & 0x3f );

      if(!current_SC)
        {
          printk("lun=%d, ", identify_msg & 0x3f );
          aha152x_panic("no disconnected command for that lun");
        }

      current_SC->SCp.phase &= ~disconnected;
      sti();

      SETPORT( SIMODE0, 0 );
      SETPORT( SIMODE1, ENPHASEMIS );
#if defined(DEBUG_RACE)
      leave_driver("(reselected) intr");
#endif
      SETBITS( DMACNTRL0, INTEN);
      return;
    }
  
  /* Check, if we aren't busy with a command */
  if(!current_SC)
    {
      /* bus is free to issue a queued command */
      if(TESTHI( SSTAT1, BUSFREE) && issue_SC)
        {
          cli();
#if defined(DEBUG_QUEUES)
          printk("i-, ");
#endif
          current_SC = remove_first_SC( &issue_SC );
          sti();

#if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
          printk("issueing command, ");
#endif
          current_SC->SCp.phase = in_selection;

  #if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
          printk("selecting %d, ", current_SC->target); 
  #endif
          SETPORT( SCSIID, (this_host << OID_) | current_SC->target );

          /* Enable interrupts for SELECTION OUT DONE and SELECTION OUT INITIATED */
          SETPORT( SXFRCTL1, ENSPCHK|ENSTIMER);

          /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */
          SETPORT( SIMODE0, ENSELDO | (disconnected_SC ? ENSELDI : 0) );
          SETPORT( SIMODE1, ENSELTIMO );

          /* Enable SELECTION OUT sequence */
          SETBITS(SCSISEQ, ENSELO | ENAUTOATNO );
        
  #if defined(DEBUG_RACE)
          leave_driver("(selecting) intr");
  #endif
          SETBITS( DMACNTRL0, INTEN );
          return;
        }

      /* No command we are busy with and no new to issue */
      printk("aha152x: ignoring spurious interrupt, nothing to do\n");
      return;
    }

  /* the bus is busy with something */

#if defined(DEBUG_INTR)
  disp_ports();
#endif

  /* we are waiting for the result of a selection attempt */
  if(current_SC->SCp.phase & in_selection)
    {
      if( TESTLO( SSTAT1, SELTO ) )
        /* no timeout */
        if( TESTHI( SSTAT0, SELDO ) )
          {
            /* clear BUS FREE interrupt */
            SETPORT( SSTAT1, CLRBUSFREE);

            /* Disable SELECTION OUT sequence */
            CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO );

            /* Disable SELECTION OUT DONE interrupt */
            CLRBITS(SIMODE0, ENSELDO);
            CLRBITS(SIMODE1, ENSELTIMO);

            if( TESTLO(SSTAT0, SELDO) )
              {
                printk("aha152x: passing bus free condition\n");

#if defined(DEBUG_RACE)
                leave_driver("(passing bus free) intr");
#endif
                SETBITS( DMACNTRL0, INTEN);

                if(current_SC->SCp.phase & aborted)
                  {
                    abort_result=1;
                    wake_up( &abortion_complete );
                  }

                aha152x_done( DID_NO_CONNECT << 16 );
                return;
              }
#if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
            printk("SELDO (SELID=%x), ", GETPORT(SELID));
#endif

            /* selection was done */
            SETPORT( SSTAT0, CLRSELDO );

#if defined(DEBUG_ABORT)
            if(current_SC->SCp.phase & aborted)
              printk("(ABORT) target selected, ");
#endif

            current_SC->SCp.phase &= ~in_selection;
            current_SC->SCp.phase |= in_other;

#if defined(DEBUG_RACE)
            leave_driver("(SELDO) intr");
#endif

            SETPORT( SCSISIG, P_MSGO );

            SETPORT( SIMODE0, 0 );
            SETPORT( SIMODE1, ENREQINIT );
            SETBITS( DMACNTRL0, INTEN);
            return;
          }
        else
          aha152x_panic("neither timeout nor selection\007");
      else
        {
#if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
          printk("SELTO, ");
#endif
	  /* end selection attempt */
          CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO );

          /* timeout */
          SETPORT( SSTAT1, CLRSELTIMO );

          SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
          SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
          SETBITS( DMACNTRL0, INTEN );
#if defined(DEBUG_RACE)
          leave_driver("(SELTO) intr");
#endif

          if(current_SC->SCp.phase & aborted)
            {
#if defined(DEBUG_ABORT)
              printk("(ABORT) selection timeout, ");
#endif
              abort_result=1;
              wake_up( &abortion_complete );
            }

          if( TESTLO( SSTAT0, SELINGO ) )
            /* ARBITRATION not won */
            aha152x_done( DID_BUS_BUSY << 16 );
          else
            /* ARBITRATION won, but SELECTION failed */
            aha152x_done( DID_NO_CONNECT << 16 );
          return;
        }
    }

  /* enable interrupt, when target leaves current phase */
  phase = getphase();
  if(!(phase & ~P_MASK))                                      /* "real" phase */
    SETPORT(SCSISIG, phase);
  SETPORT(SSTAT1, CLRPHASECHG);
  current_SC->SCp.phase =
    (current_SC->SCp.phase & ~((P_MASK|1)<<16)) | (phase << 16 );

  /* information transfer phase */
  switch( phase )
    {
    case P_MSGO:                                               /* MESSAGE OUT */
      {
        unsigned char message;

#if defined(DEBUG_INTR) || defined(DEBUG_MSGO) || defined(DEBUG_PHASES)
        printk("MESSAGE OUT, ");
#endif

        if( current_SC->SCp.phase & aborted )
          {
#if defined(DEBUG_MSGO) || defined(DEBUG_ABORT)
            printk("ABORT, ");
#endif
            message=ABORT;
          }
        else
          /* If we didn't identify yet, do it. Otherwise there's nothing to do,
             but reject (probably we got an message before, that we have to
             reject (SDTR, WDTR, etc.) */
          if( !(current_SC->SCp.phase & sent_ident))
            {
              message=IDENTIFY(can_disconnect,current_SC->lun);
#if defined(DEBUG_MSGO)
              printk("IDENTIFY (reconnect=%s;lun=%d), ", 
                      can_disconnect ? "enabled" : "disabled", current_SC->lun);
#endif
            }
          else
            {
              message=MESSAGE_REJECT;
#if defined(DEBUG_MSGO)
              printk("REJECT, ");
#endif
            }
          
        CLRBITS( SXFRCTL0, ENDMA);

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

        /* wait for data latch to become ready or a phase change */
        while( TESTLO( DMASTAT, INTSTAT ) )
          ;

        if( TESTHI( SSTAT1, PHASEMIS ) )
          aha152x_panic("unable to send message");

        /* Leave MESSAGE OUT after transfer */
        SETPORT( SSTAT1, CLRATNO);

        SETPORT( SCSIDAT, message );

        make_acklow();
        getphase();

        if(message==IDENTIFY(can_disconnect,current_SC->lun))

⌨️ 快捷键说明

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