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

📄 seagate.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
        return retcode (st0x_aborted);#endif      DPRINTK (PHASE_SELECTION, "scsi%d : phase = SELECTION\n", hostno);      clock = jiffies + ST0X_SELECTION_DELAY;/* * Arbitration/selection procedure : * 1.  Disable drivers * 2.  Write HOST adapter address bit * 3.  Set start arbitration. * 4.  We get either ARBITRATION COMPLETE or SELECT at this *     point. * 5.  OR our ID and targets on bus. * 6.  Enable SCSI drivers and asserted SEL and ATTN */#ifdef ARBITRATE      save_flags (flags);      cli ();      WRITE_CONTROL (0);      WRITE_DATA ((controller_type == SEAGATE) ? 0x80 : 0x40);      WRITE_CONTROL (CMD_START_ARB);      restore_flags (flags);      ULOOP( ST0X_SELECTION_DELAY * 10000 ) {	status_read = STATUS;	if (status_read & STAT_ARB_CMPL) break;	if (st0x_aborted)	/* FIXME: What? We are going to do something even after abort? */	   break;	if (TIMEOUT || (status_read & STAT_SEL)) {	  printk( "scsi%d : arbitration lost or timeout.\n", hostno );	  WRITE_CONTROL (BASE_CMD);	  return retcode (DID_NO_CONNECT);	}      }      DPRINTK (PHASE_SELECTION, "scsi%d : arbitration complete\n", hostno);#endif/* *    When the SCSI device decides that we're gawking at it, it will *    respond by asserting BUSY on the bus. * *    Note : the Seagate ST-01/02 product manual says that we should *    twiddle the DATA register before the control register.    However, *    this does not work reliably so we do it the other way around. * *    Probably could be a problem with arbitration too, we really should *    try this with a SCSI protocol or logic analyzer to see what is *    going on. */       tmp_data = (unsigned char) ((1 << target) | (controller_type == SEAGATE ? 0x80 : 0x40));       tmp_control = BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL | (reselect ? CMD_ATTN : 0);       save_flags(flags);       cli();#ifdef OLDCNTDATASCEME#ifdef SWAPCNTDATA       WRITE_CONTROL (tmp_control);       WRITE_DATA (tmp_data);#else       WRITE_DATA (tmp_data);       WRITE_CONTROL (tmp_control);#endif#else       tmp_control ^= CMD_BSY;		/* This is guesswork. What used to be in driver	   */       WRITE_CONTROL (tmp_control);	/* could never work: it sent data into control	   */       WRITE_DATA (tmp_data);		/* register and control info into data. Hopefully  */       tmp_control ^= CMD_BSY;		/* fixed, but order of first two may be wrong.     */       WRITE_CONTROL (tmp_control);	                              /* -- pavel@ucw.cz   */#endif              restore_flags (flags);       ULOOP( 250*1000 ) {	 if (st0x_aborted) {/* *    If we have been aborted, and we have a command in progress, IE the *      target still has BSY asserted, then we will reset the bus, and *      notify the midlevel driver to expect sense. */	   WRITE_CONTROL (BASE_CMD);	   if (STATUS & STAT_BSY) {	     printk ("scsi%d : BST asserted after we've been aborted.\n", hostno);	     seagate_st0x_reset (NULL, 0);	     return retcode (DID_RESET);	   }	   return retcode (st0x_aborted);	 }	 if (STATUS & STAT_BSY) break;	 if (TIMEOUT) {	   DPRINTK (PHASE_SELECTION, "scsi%d : NO CONNECT with target %d, stat = %x \n",		    hostno, target, STATUS);	   return retcode (DID_NO_CONNECT);	 }       }/* Establish current pointers.  Take into account scatter / gather */      if ((nobuffs = SCint->use_sg))      {#if (DEBUG & DEBUG_SG)        {          int i;          printk ("scsi%d : scatter gather requested, using %d buffers.\n",                  hostno, nobuffs);          for (i = 0; i < nobuffs; ++i)            printk ("scsi%d : buffer %d address = %08x length = %d\n",                    hostno, i, buffer[i].address, buffer[i].length);        }#endif        buffer = (struct scatterlist *) SCint->buffer;        len = buffer->length;        data = (unsigned char *) buffer->address;      }      else      {        DPRINTK (DEBUG_SG, "scsi%d : scatter gather not requested.\n", hostno);        buffer = NULL;        len = SCint->request_bufflen;        data = (unsigned char *) SCint->request_buffer;      }      DPRINTK (PHASE_DATAIN | PHASE_DATAOUT, "scsi%d : len = %d\n", hostno, len);      break;#ifdef LINKED    case LINKED_RIGHT:      break;    case LINKED_WRONG:      break;#endif  }                                     /* end of switch(reselect) *//* *    There are several conditions under which we wish to send a message : *      1.  When we are allowing disconnect / reconnect, and need to establish *          the I_T_L nexus via an IDENTIFY with the DiscPriv bit set. * *      2.  When we are doing linked commands, are have the wrong I_T_L nexus *          established and want to send an ABORT message. *//* GCC does not like an ifdef inside a macro, so do it the hard way. */#ifdef LINKED  WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE |                 (((reselect == CAN_RECONNECT)                   || (reselect == LINKED_WRONG)                  )? CMD_ATTN : 0));#else  WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE |                 (((reselect == CAN_RECONNECT)                  )? CMD_ATTN : 0));#endif/* *    INFORMATION TRANSFER PHASE * *      The nasty looking read / write inline assembler loops we use for *      DATAIN and DATAOUT phases are approximately 4-5 times as fast as *      the 'C' versions - since we're moving 1024 bytes of data, this *      really adds up. * *      SJT: The nasty-looking assembler is gone, so it's slower. * */  DPRINTK (PHASE_ETC, "scsi%d : phase = INFORMATION TRANSFER\n", hostno);  incommand = 1;  transfersize = SCint->transfersize;  underflow = SCint->underflow;/* *    Now, we poll the device for status information, *      and handle any requests it makes.  Note that since we are unsure of *      how much data will be flowing across the system, etc and cannot *      make reasonable timeouts, that we will instead have the midlevel *      driver handle any timeouts that occur in this phase. */  while (((status_read = STATUS) & STAT_BSY) && !st0x_aborted && !done)  {#ifdef PARITY    if (status_read & STAT_PARITY)    {      printk ("scsi%d : got parity error\n", hostno);      st0x_aborted = DID_PARITY;    }#endif    if (status_read & STAT_REQ)    {#if ((DEBUG & PHASE_ETC) == PHASE_ETC)      if ((newphase = (status_read & REQ_MASK)) != phase)      {        phase = newphase;        switch (phase)        {          case REQ_DATAOUT:            printk ("scsi%d : phase = DATA OUT\n", hostno);            break;          case REQ_DATAIN:            printk ("scsi%d : phase = DATA IN\n", hostno);            break;          case REQ_CMDOUT:            printk ("scsi%d : phase = COMMAND OUT\n", hostno);            break;          case REQ_STATIN:            printk ("scsi%d : phase = STATUS IN\n", hostno);            break;          case REQ_MSGOUT:            printk ("scsi%d : phase = MESSAGE OUT\n", hostno);            break;          case REQ_MSGIN:            printk ("scsi%d : phase = MESSAGE IN\n", hostno);            break;          default:            printk ("scsi%d : phase = UNKNOWN\n", hostno);            st0x_aborted = DID_ERROR;        }      }#endif      switch (status_read & REQ_MASK)      {        case REQ_DATAOUT:/* * If we are in fast mode, then we simply splat the data out * in word-sized chunks as fast as we can. */          if (!len)          {#if 0            printk ("scsi%d: underflow to target %d lun %d \n", hostno, target, lun);            st0x_aborted = DID_ERROR;            fast = 0;#endif            break;          }          if (fast && transfersize && !(len % transfersize)              && (len >= transfersize)#ifdef FAST32              && !(transfersize % 4)#endif            )          {            DPRINTK (DEBUG_FAST,		     "scsi%d : FAST transfer, underflow = %d, transfersize = %d\n"                    "         len = %d, data = %08x\n",                  hostno, SCint->underflow, SCint->transfersize, len, data);/* SJT: Start. Fast Write */#ifdef SEAGATE_USE_ASM            __asm__(                "cld\n\t"#ifdef FAST32                "shr $2, %%ecx\n\t"                "1:\t"                "lodsl\n\t"                "movl %%eax, (%%edi)\n\t"#else                "1:\t"                "lodsb\n\t"                "movb %%al, (%%edi)\n\t"#endif                "loop 1b;"/* output */    :/* input */     : "D" (phys_to_virt(st0x_dr)), "S" (data), "c" (SCint->transfersize) /* clobbered */ : "eax", "ecx", "esi" );#else /* SEAGATE_USE_ASM */            {#ifdef FAST32              unsigned int *iop = phys_to_virt (st0x_dr);              const unsigned int *dp = (unsigned int *) data;              int xferlen = transfersize >> 2;#else              unsigned char *iop = phys_to_virt (st0x_dr);              const unsigned char *dp = data;              int xferlen = transfersize;#endif              for (; xferlen; --xferlen)                *iop = *dp++;            }#endif /* SEAGATE_USE_ASM *//* SJT: End */            len -= transfersize;            data += transfersize;            DPRINTK (DEBUG_FAST,		     "scsi%d : FAST transfer complete len = %d data = %08x\n",                    hostno, len, data);          }          else          {/* *    We loop as long as we are in a data out phase, there is data to send, *      and BSY is still active. *//* SJT: Start. Slow Write. */#ifdef SEAGATE_USE_ASM/* *      We loop as long as we are in a data out phase, there is data to send,  *      and BSY is still active. *//* Local variables : len = ecx , data = esi,                      st0x_cr_sr = ebx, st0x_dr =  edi*/            __asm__ (            /* Test for any data here at all. */                    "orl %%ecx, %%ecx\n\t"                    "jz 2f\n\t"                    "cld\n\t"/*                    "movl " SYMBOL_NAME_STR(st0x_cr_sr) ", %%ebx\n\t"  *//*                    "movl " SYMBOL_NAME_STR(st0x_dr) ", %%edi\n\t"  */                "1:\t"                    "movb (%%ebx), %%al\n\t"            /* Test for BSY */                    "test $1, %%al\n\t"                    "jz 2f\n\t"            /* Test for data out phase - STATUS & REQ_MASK should be                REQ_DATAOUT, which is 0. */                    "test $0xe, %%al\n\t"                    "jnz 2f\n\t"            /* Test for REQ */                          "test $0x10, %%al\n\t"                    "jz 1b\n\t"                    "lodsb\n\t"                    "movb %%al, (%%edi)\n\t"                    "loop 1b\n\t"                "2:\n"/* output */    : "=S" (data), "=c" (len) /* input */     : "0" (data), "1" (len), "b" (phys_to_virt(st0x_cr_sr)), "D" (phys_to_virt(st0x_dr)) /* clobbered */ : "eax", "ebx", "edi"); #else /* SEAGATE_USE_ASM */            while (len)            {              unsigned char stat;              stat = STATUS;              if (!(stat & STAT_BSY) || ((stat & REQ_MASK) != REQ_DATAOUT))                break;              if (stat & STAT_REQ)              {                WRITE_DATA (*data++);                --len;              }            }#endif /* SEAGATE_USE_ASM *//* SJT: End. */          }          if (!len && nobuffs)          {            --nobuffs;            ++buffer;            len = buffer->length;            data = (unsigned char *) buffer->address;            DPRINTK (DEBUG_SG,		    "scsi%d : next scatter-gather buffer len = %d address = %08x\n",                    hostno, len, data);          }          break;        case REQ_DATAIN:#ifdef SLOW_RATE          if (borken)          {#if (DEBUG & (PHASE_DATAIN))            transfered += len;#endif            for (;                 len && (STATUS & (REQ_MASK | STAT_REQ)) == (REQ_DATAIN |                                                             STAT_REQ)                 ; --len)            {              *data++ = DATA;              borken_wait ();            }#if (DEBUG & (PHASE_DATAIN))            transfered -= len;#endif          }          else#endif            if (fast && transfersize && !(len % transfersize) &&                (len >= transfersize)#ifdef FAST32                && !(transfersize % 4)#endif            )          {            DPRINTK (DEBUG_FAST,		     "scsi%d : FAST transfer, underflow = %d, transfersize = %d\n"                    "         len = %d, data = %08x\n",                  hostno, SCint->underflow, SCint->transfersize, len, data);/* SJT: Start. Fast Read */#ifdef SEAGATE_USE_ASM            __asm__(                    "cld\n\t"#ifdef FAST32                    "shr $2, %%ecx\n\t"                "1:\t"                    "movl (%%esi), %%eax\n\t"                    "stosl\n\t"#else                "1:\t"                    "movb (%%esi), %%al\n\t"                    "stosb\n\t"#endif                    "loop 1b\n\t"/* output */        : /* input */         : "S" (phys_to_virt(st0x_dr)), "D" (data), "c" (SCint->transfersize) /* clobbered */     : "eax", "ecx", "edi");#else /* SEAGATE_USE_ASM */            {#ifdef FAST32              const unsigned int *iop = phys_to_virt (st0x_dr);              unsigned int *dp = (unsigned int *) data;              int xferlen = len >> 2;#else              const unsigned char *iop = phys_to_virt (st0x_dr);              unsigned char *dp = data;              int xferlen = len;#endif              for (; xferlen; --xferlen)                *dp++ = *iop;            }#endif /* SEAGATE_USE_ASM *//* SJT: End */            len -= transfersize;            data += transfersize;#if (DEBUG & PHASE_DATAIN)            printk ("scsi%d: transfered += %d\n", hostno, transfersize);            transfered += transfersize;#endif            DPRINTK (DEBUG_FAST,		     "scsi%d : FAST transfer complete len = %d data = %08x\n",                    hostno, len, data);          }          else          {#if (DEBUG & PHASE_DATAIN)            printk ("scsi%d: transfered += %d\n", hostno, len);            transfered += len;          /* Assume we'll transfer it all, then                                           subtract what we *didn't* transfer */

⌨️ 快捷键说明

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