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

📄 seagate.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
                    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 */#endif/* *    We loop as long as we are in a data in phase, there is room to read, *      and BSY is still active *//* SJT: Start. */#ifdef SEAGATE_USE_ASMint __dummy_3,__dummy_4;/* Dummy clobbering variables for the new gcc-2.95 *//* *      We loop as long as we are in a data in phase, there is room to read,  *      and BSY is still active */            /* Local variables : ecx = len, edi = data                                 esi = st0x_cr_sr, ebx = st0x_dr */            __asm__ (            /* Test for room to read */                "orl %%ecx, %%ecx\n\t"                "jz 2f\n\t"                "cld\n\t"/*                "movl " SYMBOL_NAME_STR(st0x_cr_sr) ", %%esi\n\t"  *//*                "movl " SYMBOL_NAME_STR(st0x_dr) ", %%ebx\n\t"  */            "1:\t"                "movb (%%esi), %%al\n\t"            /* Test for BSY */                "test $1, %%al\n\t"                "jz 2f\n\t"            /* Test for data in phase - STATUS & REQ_MASK should be REQ_DATAIN,                = STAT_IO, which is 4. */                "movb $0xe, %%ah\n\t"                      "andb %%al, %%ah\n\t"                "cmpb $0x04, %%ah\n\t"                "jne 2f\n\t"            /* Test for REQ */                      "test $0x10, %%al\n\t"                "jz 1b\n\t"                "movb (%%ebx), %%al\n\t"                      "stosb\n\t"                   "loop 1b\n\t"            "2:\n"/* output */    : "=D" (data), "=c" (len) ,"=S" (__dummy_3) ,"=b" (__dummy_4)/* input */     : "0" (data), "1" (len), "2" (phys_to_virt(st0x_cr_sr)), "3" (phys_to_virt(st0x_dr)) /* clobbered */ : "eax" ); #else /* SEAGATE_USE_ASM */            while (len)            {              unsigned char stat;              stat = STATUS;              if (!(stat & STAT_BSY) || ((stat & REQ_MASK) != REQ_DATAIN))                break;              if (stat & STAT_REQ)              {                *data++ = DATA;                --len;              }            }#endif /* SEAGATE_USE_ASM *//* SJT: End. */#if (DEBUG & PHASE_DATAIN)            printk ("scsi%d: transfered -= %d\n", hostno, len);            transfered -= len;          /* Since we assumed all of Len got  *                                           transfered, correct our mistake */#endif          }          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_CMDOUT:          while (((status_read = STATUS) & STAT_BSY) &&                 ((status_read & REQ_MASK) == REQ_CMDOUT))            if (status_read & STAT_REQ)            {              WRITE_DATA (*(const unsigned char *) cmnd);              cmnd = 1 + (const unsigned char *) cmnd;#ifdef SLOW_RATE              if (borken)                borken_wait ();#endif            }          break;        case REQ_STATIN:          status = DATA;          break;        case REQ_MSGOUT:/* *    We can only have sent a MSG OUT if we requested to do this *      by raising ATTN.  So, we must drop ATTN. */          WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE);/* *    If we are reconnecting, then we must send an IDENTIFY message in *       response  to MSGOUT. */          switch (reselect)          {            case CAN_RECONNECT:              WRITE_DATA (IDENTIFY (1, lun));              DPRINTK (PHASE_RESELECT | PHASE_MSGOUT, "scsi%d : sent IDENTIFY message.\n", hostno);              break;#ifdef LINKED            case LINKED_WRONG:              WRITE_DATA (ABORT);              linked_connected = 0;              reselect = CAN_RECONNECT;              goto connect_loop;              DPRINTK (PHASE_MSGOUT | DEBUG_LINKED, 		       "scsi%d : sent ABORT message to cancel incorrect I_T_L nexus.\n", hostno);#endif /* LINKED */              DPRINTK (DEBUG_LINKED, "correct\n");            default:              WRITE_DATA (NOP);              printk ("scsi%d : target %d requested MSGOUT, sent NOP message.\n", hostno, target);          }          break;        case REQ_MSGIN:          switch (message = DATA)          {            case DISCONNECT:	      DANY ("seagate: deciding to disconnect\n");              should_reconnect = 1;              current_data = data;      /* WDE add */              current_buffer = buffer;              current_bufflen = len;    /* WDE add */              current_nobuffs = nobuffs;#ifdef LINKED              linked_connected = 0;#endif              done = 1;              DPRINTK ((PHASE_RESELECT | PHASE_MSGIN), "scsi%d : disconnected.\n", hostno);              break;#ifdef LINKED            case LINKED_CMD_COMPLETE:            case LINKED_FLG_CMD_COMPLETE:#endif            case COMMAND_COMPLETE:/* * Note : we should check for underflow here. */              DPRINTK (PHASE_MSGIN, "scsi%d : command complete.\n", hostno);              done = 1;              break;            case ABORT:              DPRINTK (PHASE_MSGIN, "scsi%d : abort message.\n", hostno);              done = 1;              break;            case SAVE_POINTERS:              current_buffer = buffer;              current_bufflen = len;    /* WDE add */              current_data = data;      /* WDE mod */              current_nobuffs = nobuffs;              DPRINTK (PHASE_MSGIN, "scsi%d : pointers saved.\n", hostno);              break;            case RESTORE_POINTERS:              buffer = current_buffer;              cmnd = current_cmnd;              data = current_data;      /* WDE mod */              len = current_bufflen;              nobuffs = current_nobuffs;              DPRINTK (PHASE_MSGIN, "scsi%d : pointers restored.\n", hostno);              break;            default:/* *    IDENTIFY distinguishes itself from the other messages by setting the *      high byte. [FIXME: should not this read "the high bit"? - pavel@ucw.cz] * *      Note : we need to handle at least one outstanding command per LUN, *      and need to hash the SCSI command for that I_T_L nexus based on the *      known ID (at this point) and LUN. */              if (message & 0x80)              {                DPRINTK (PHASE_MSGIN, "scsi%d : IDENTIFY message received from id %d, lun %d.\n",                        hostno, target, message & 7);              }              else              {/* *      We should go into a MESSAGE OUT phase, and send  a MESSAGE_REJECT *      if we run into a message that we don't like.  The seagate driver *      needs some serious restructuring first though. */                DPRINTK (PHASE_MSGIN, 			 "scsi%d : unknown message %d from target %d.\n", hostno, message, target);              }          }          break;        default:          printk ("scsi%d : unknown phase.\n", hostno);          st0x_aborted = DID_ERROR;      }                                 /* end of switch (status_read &                                           REQ_MASK) */#ifdef SLOW_RATE/* * I really don't care to deal with borken devices in each single * byte transfer case (ie, message in, message out, status), so * I'll do the wait here if necessary. */      if (borken)        borken_wait ();#endif    }                                   /* if(status_read & STAT_REQ) ends */  }                                     /* while(((status_read = STATUS)...)                                           ends */  DPRINTK (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT, 	   "scsi%d : Transfered %d bytes\n", hostno, transfered);#if (DEBUG & PHASE_EXIT)#if 0                                   /* Doesn't work for scatter/gather */  printk ("Buffer : \n");  for (i = 0; i < 20; ++i)    printk ("%02x  ", ((unsigned char *) data)[i]);     /* WDE mod */  printk ("\n");#endif  printk ("scsi%d : status = ", hostno);  print_status (status);  printk ("message = %02x\n", message);#endif/* We shouldn't reach this until *after* BSY has been deasserted */#ifdef LINKED  else  {/* * Fix the message byte so that unsuspecting high level drivers don't * puke when they see a LINKED COMMAND message in place of the COMMAND * COMPLETE they may be expecting.  Shouldn't be necessary, but it's * better to be on the safe side. * * A non LINKED* message byte will indicate that the command completed, * and we are now disconnected. */    switch (message)    {      case LINKED_CMD_COMPLETE:      case LINKED_FLG_CMD_COMPLETE:        message = COMMAND_COMPLETE;        linked_target = current_target;        linked_lun = current_lun;        linked_connected = 1;	DPRINTK (DEBUG_LINKED, "scsi%d : keeping I_T_L nexus established"		 "for linked command.\n", hostno);    /* We also will need to adjust status to accommodate intermediate       conditions. */        if ((status == INTERMEDIATE_GOOD) ||            (status == INTERMEDIATE_C_GOOD))          status = GOOD;        break;/* * We should also handle what are "normal" termination messages * here (ABORT, BUS_DEVICE_RESET?, and COMMAND_COMPLETE individually, * and flake if things aren't right. */      default:        DPRINTK (DEBUG_LINKED, "scsi%d : closing I_T_L nexus.\n", hostno);        linked_connected = 0;    }  }#endif /* LINKED */  if (should_reconnect)  {    DPRINTK (PHASE_RESELECT, "scsi%d : exiting seagate_st0x_queue_command()"	     "with reconnect enabled.\n", hostno);    WRITE_CONTROL (BASE_CMD | CMD_INTR);  }  else    WRITE_CONTROL (BASE_CMD);  return retcode (st0x_aborted);}                                       /* end of internal_command */int seagate_st0x_abort (Scsi_Cmnd * SCpnt){  st0x_aborted = DID_ABORT;  return SCSI_ABORT_PENDING;}#undef ULOOP#undef TIMEOUT/* * the seagate_st0x_reset function resets the SCSI bus  */int seagate_st0x_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags){/* No timeouts - this command is going to fail because it was reset. */  DANY ("scsi%d: Reseting bus... ", hostno );/* assert  RESET signal on SCSI bus.  */  WRITE_CONTROL (BASE_CMD | CMD_RST);  udelay( 20*1000 );  WRITE_CONTROL (BASE_CMD);  st0x_aborted = DID_RESET;  DANY ("done.\n");  return SCSI_RESET_WAKEUP;}/* Eventually this will go into an include file, but this will be later */static Scsi_Host_Template driver_template = SEAGATE_ST0X;#include "scsi_module.c"

⌨️ 快捷键说明

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