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

📄 ibmmca.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	 return;      }   }   last_scsi_command(ihost_index)[ldn] = NO_SCSI;   last_scsi_type(ihost_index)[ldn] = 0;   cmd = ld(ihost_index)[ldn].cmd;   ld(ihost_index)[ldn].cmd = NULL;#ifdef IM_DEBUG_TIMEOUT   if (cmd) {      if ((cmd->target == TIMEOUT_PUN)&&(cmd->lun == TIMEOUT_LUN)) {	 printk("IBM MCA SCSI: Ignoring interrupt from pun=%x, lun=%x.\n",		cmd->target, cmd->lun);	 return;      }   }#endif   /*if no command structure, just return, else clear cmd */   if (!cmd) return;#ifdef IM_DEBUG_INT   printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n",	  cmd->cmnd[0], intr_reg,	  ld(ihost_index)[ldn].tsb.dev_status,	  ld(ihost_index)[ldn].tsb.cmd_status,	  ld(ihost_index)[ldn].tsb.dev_error,	  ld(ihost_index)[ldn].tsb.cmd_error);#endif   /*if this is end of media read/write, may turn off PS/2 disk led */   if ((ld(ihost_index)[ldn].device_type!=TYPE_NO_LUN)&&       (ld(ihost_index)[ldn].device_type!=TYPE_NO_DEVICE)) {      /* only access this, if there was a valid device addressed */      if (--disk_rw_in_progress == 0) PS2_DISK_LED_OFF ();   }   /* IBM describes the status-mask to be 0x1e, but this is not conform    * with SCSI-definition, I suppose, the reason for it is that IBM    * adapters do not support CMD_TERMINATED, TASK_SET_FULL and    * ACA_ACTIVE as returning statusbyte information. (ML) */   if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) {      cmd->result = (unsigned char)(ld(ihost_index)[ldn].tsb.dev_status & 0x1e);      IBM_DS(ihost_index).total_errors++;   } else     cmd->result = 0;   /* write device status into cmd->result, and call done function */   if (lastSCSI == NO_SCSI) { /* unexpected interrupt :-( */      cmd->result |= DID_BAD_INTR << 16;      printk("IBM MCA SCSI: WARNING - Interrupt from non-pending SCSI-command!\n");   } else /* things went right :-) */     cmd->result |= DID_OK << 16;   if (cmd->scsi_done) (cmd->scsi_done)(cmd);   return;}static void issue_cmd (int host_index, unsigned long cmd_reg,		       unsigned char attn_reg){   unsigned long flags;   /* must wait for attention reg not busy */   while (1) {      IBMLOCK      if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY)) break;      IBMUNLOCK   }   /* write registers and enable system interrupts */   outl (cmd_reg, IM_CMD_REG(host_index));   outb (attn_reg, IM_ATTN_REG(host_index));   IBMUNLOCK   return;}static void internal_done (Scsi_Cmnd * cmd){   cmd->SCp.Status++;   return;}/* SCSI-SCB-command for device_inquiry */static int device_inquiry(int host_index, int ldn){   int retr;   struct im_scb *scb;   struct im_tsb *tsb;   unsigned char *buf;   scb = &(ld(host_index)[ldn].scb);   tsb = &(ld(host_index)[ldn].tsb);   buf = (unsigned char *)(&(ld(host_index)[ldn].buf));   ld(host_index)[ldn].tsb.dev_status = 0; /* prepare statusblock */   for (retr=0; retr<3; retr++) {      /* fill scb with inquiry command */      scb->command = IM_DEVICE_INQUIRY_CMD | IM_NO_DISCONNECT;      scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;      last_scsi_command(host_index)[ldn] = IM_DEVICE_INQUIRY_CMD;      last_scsi_type(host_index)[ldn] = IM_SCB;      scb->sys_buf_adr = virt_to_bus(buf);      scb->sys_buf_length = 255; /* maximum bufferlength gives max info */      scb->tsb_adr = virt_to_bus(tsb);      /* issue scb to passed ldn, and busy wait for interrupt */      got_interrupt(host_index) = 0;      issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);      while (!got_interrupt(host_index))	barrier ();      /*if command succesful, break */      if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)||	  (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))	return 1;   }   /*if all three retries failed, return "no device at this ldn" */   if (retr >= 3)     return 0;   else     return 1;}static int read_capacity(int host_index, int ldn){   int retr;   struct im_scb *scb;   struct im_tsb *tsb;   unsigned char *buf;   scb = &(ld(host_index)[ldn].scb);   tsb = &(ld(host_index)[ldn].tsb);   buf = (unsigned char *)(&(ld(host_index)[ldn].buf));   ld(host_index)[ldn].tsb.dev_status = 0;   for (retr=0; retr<3; retr++) {      /*fill scb with read capacity command */      scb->command = IM_READ_CAPACITY_CMD;      scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;      last_scsi_command(host_index)[ldn] = IM_READ_CAPACITY_CMD;      last_scsi_type(host_index)[ldn] = IM_SCB;      scb->sys_buf_adr = virt_to_bus(buf);      scb->sys_buf_length = 8;      scb->tsb_adr = virt_to_bus(tsb);      /*issue scb to passed ldn, and busy wait for interrupt */      got_interrupt(host_index) = 0;      issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);      while (!got_interrupt(host_index))	barrier ();      /*if got capacity, get block length and return one device found */      if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)||	  (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))	return 1;   }   /*if all three retries failed, return "no device at this ldn" */   if (retr >= 3)     return 0;   else     return 1;}static int get_pos_info(int host_index){   int retr;   struct im_scb *scb;   struct im_tsb *tsb;   unsigned char *buf;   scb = &(ld(host_index)[MAX_LOG_DEV].scb);   tsb = &(ld(host_index)[MAX_LOG_DEV].tsb);   buf = (unsigned char *)(&(ld(host_index)[MAX_LOG_DEV].buf));   ld(host_index)[MAX_LOG_DEV].tsb.dev_status = 0;   for (retr=0; retr<3; retr++) {      /*fill scb with get_pos_info command */      scb->command = IM_GET_POS_INFO_CMD;      scb->enable = IM_READ_CONTROL | IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;      last_scsi_command(host_index)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD;      last_scsi_type(host_index)[MAX_LOG_DEV] = IM_SCB;      scb->sys_buf_adr = virt_to_bus(buf);      if (special(host_index)==IBM_SCSI2_FW)	scb->sys_buf_length = 256; /* get all info from F/W adapter */      else	scb->sys_buf_length = 18; /* get exactly 18 bytes for other SCSI */      scb->tsb_adr = virt_to_bus(tsb);      /*issue scb to ldn=15, and busy wait for interrupt */      got_interrupt(host_index) = 0;      issue_cmd (host_index, virt_to_bus(scb), IM_SCB | MAX_LOG_DEV);      while (!got_interrupt(host_index))	barrier ();      /*if got POS-stuff, get block length and return one device found */      if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)||	  (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))	return 1;   }   /* if all three retries failed, return "no device at this ldn" */   if (retr >= 3)     return 0;   else     return 1;}/* SCSI-immediate-command for assign. This functions maps/unmaps specific ldn-numbers on SCSI (PUN,LUN). It is needed for presetting of the subsystem and for dynamical remapping od ldns. */static int immediate_assign(int host_index, unsigned int pun,                            unsigned int lun, unsigned int ldn,                            unsigned int operation){   int retr;   unsigned long imm_cmd;   for (retr=0; retr<3; retr++) {      /* select mutation level of the SCSI-adapter */      switch (special(host_index)) {       case IBM_SCSI2_FW:	 imm_cmd = (unsigned long)(IM_ASSIGN_IMM_CMD);	 imm_cmd |= (unsigned long)((lun & 7) << 24);	 imm_cmd |= (unsigned long)((operation & 1) << 23);	 imm_cmd |= (unsigned long)((pun & 7)<< 20)|((pun & 8)<< 24);	 imm_cmd |= (unsigned long)((ldn & 15) << 16);	 break;       default:	 imm_cmd = inl(IM_CMD_REG(host_index));	 imm_cmd &= (unsigned long)(0xF8000000); /* keep reserved bits */	 imm_cmd |= (unsigned long)(IM_ASSIGN_IMM_CMD);	 imm_cmd |= (unsigned long)((lun & 7) << 24);	 imm_cmd |= (unsigned long)((operation & 1) << 23);	 imm_cmd |= (unsigned long)((pun & 7) << 20);	 imm_cmd |= (unsigned long)((ldn & 15) << 16);	 break;      }      last_scsi_command(host_index)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD;      last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD;      got_interrupt(host_index) = 0;      issue_cmd (host_index, (unsigned long)(imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);      while (!got_interrupt(host_index))	barrier ();      /*if command succesful, break */      if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)	return 1;   }   if (retr >= 3)     return 0;   else     return 1;}static int immediate_feature(int host_index, unsigned int speed,			     unsigned int timeout){   int retr;   unsigned long imm_cmd;   for (retr=0; retr<3; retr++) {      /* select mutation level of the SCSI-adapter */      imm_cmd  = IM_FEATURE_CTR_IMM_CMD;      imm_cmd |= (unsigned long)((speed & 0x7) << 29);      imm_cmd |= (unsigned long)((timeout & 0x1fff) << 16);      last_scsi_command(host_index)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD;      last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD;      got_interrupt(host_index) = 0;      /* we need to run into command errors in order to probe for the       * right speed! */      global_command_error_excuse = 1;      issue_cmd (host_index, (unsigned long)(imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);      while (!got_interrupt(host_index))	barrier ();      if (global_command_error_excuse == CMD_FAIL) {	 global_command_error_excuse = 0;	 return 2;      } else	global_command_error_excuse = 0;      /*if command succesful, break */      if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)	return 1;   }   if (retr >= 3)     return 0;   else     return 1;}#ifdef CONFIG_IBMMCA_SCSI_DEV_RESETstatic int immediate_reset(int host_index, unsigned int ldn){   int retries;   int ticks;   unsigned long imm_command;   for (retries=0; retries<3; retries ++) {      imm_command = inl(IM_CMD_REG(host_index));      imm_command &= (unsigned long)(0xFFFF0000); /* keep reserved bits */      imm_command |= (unsigned long)(IM_RESET_IMM_CMD);      last_scsi_command(host_index)[ldn] = IM_RESET_IMM_CMD;      last_scsi_type(host_index)[ldn] = IM_IMM_CMD;      got_interrupt(host_index) = 0;      reset_status(host_index) = IM_RESET_IN_PROGRESS;      issue_cmd (host_index, (unsigned long)(imm_command), IM_IMM_CMD | ldn);      ticks = IM_RESET_DELAY*HZ;      while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks) {	 udelay((1+999/HZ)*1000);	 barrier();      }      /* if reset did not complete, just complain */      if (!ticks) {	 printk("IBM MCA SCSI: reset did not complete within %d seconds.\n",		IM_RESET_DELAY);	 reset_status(host_index) = IM_RESET_FINISHED_OK;	 /* did not work, finish */	 return 1;      }      /*if command succesful, break */      if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)	return 1;   }   if (retries >= 3)     return 0;   else     return 1;}#endif/* type-interpreter for physical device numbers */static char *ti_p(int dev){   switch (dev) {    case TYPE_IBM_SCSI_ADAPTER: return("A");    case TYPE_DISK:             return("D");    case TYPE_TAPE:             return("T");    case TYPE_PROCESSOR:        return("P");    case TYPE_WORM:             return("W");    case TYPE_ROM:              return("R");    case TYPE_SCANNER:          return("S");    case TYPE_MOD:              return("M");    case TYPE_MEDIUM_CHANGER:   return("C");    case TYPE_NO_LUN:           return("+"); /* show NO_LUN */   }   return("-"); /* TYPE_NO_DEVICE and others */}/* interpreter for logical device numbers (ldn) */static char *ti_l(int val){

⌨️ 快捷键说明

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