📄 3w-xxxx.c
字号:
if (tw_dev->state[request_id] != TW_S_PENDING) { printk(KERN_WARNING "3w-xxxx: scsi%d: Found request id that wasn't pending.\n", tw_dev->host->host_no); break; } if (tw_post_command_packet(tw_dev, request_id)==0) { if (tw_dev->pending_head == TW_Q_LENGTH-1) { tw_dev->pending_head = TW_Q_START; } else { tw_dev->pending_head = tw_dev->pending_head + 1; } tw_dev->pending_request_count--; } else { break; } } /* If there are no more pending requests, we mask command interrupt */ if (tw_dev->pending_request_count == 0) tw_mask_command_interrupt(tw_dev); } /* Handle response interrupt */ if (do_response_interrupt) { /* Drain the response queue from the board */ while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { response_que.value = inl(response_que_addr); request_id = response_que.u.response_id; command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; error = 0; if (command_packet->status != 0) { dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Bad response, status = 0x%x, flags = 0x%x, unit = 0x%x.\n", command_packet->status, command_packet->flags, command_packet->byte3.unit); tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit); error = 1; } if (tw_dev->state[request_id] != TW_S_POSTED) { printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", tw_dev->host->host_no, request_id, command_packet->byte0.opcode); error = 1; } if (TW_STATUS_ERRORS(status_reg_value)) { tw_decode_bits(tw_dev, status_reg_value); error = 1; } dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id); /* Check for internal command */ if (tw_dev->srb[request_id] == 0) { dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n"); error = tw_aen_complete(tw_dev, request_id); if (error) { printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no); } status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n"); tw_decode_bits(tw_dev, status_reg_value); } } else { switch (tw_dev->srb[request_id]->cmnd[0]) { case READ_10: case READ_6: dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10/READ_6\n"); break; case WRITE_10: case WRITE_6: dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n"); break; case INQUIRY: dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n"); error = tw_scsiop_inquiry_complete(tw_dev, request_id); break; case READ_CAPACITY: dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_CAPACITY\n"); error = tw_scsiop_read_capacity_complete(tw_dev, request_id); break; case TW_IOCTL: dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TW_IOCTL\n"); error = tw_ioctl_complete(tw_dev, request_id); break; default: printk(KERN_WARNING "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x.\n", tw_dev->host->host_no, tw_dev->srb[request_id]->cmnd[0]); tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16); tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); } if (error == 1) { /* Tell scsi layer there was an error */ dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Scsi Error.\n"); tw_dev->srb[request_id]->result = (DID_RESET << 16); } if (error == 0) { /* Tell scsi layer command was a success */ tw_dev->srb[request_id]->result = (DID_OK << 16); } if (error != 2) { tw_dev->state[request_id] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, request_id); tw_dev->posted_request_count--; tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); } status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n"); tw_decode_bits(tw_dev, status_reg_value); } } } } spin_unlock(&tw_dev->tw_lock); } spin_unlock_irqrestore(&io_request_lock, flags); clear_bit(TW_IN_INTR, &tw_dev->flags);} /* End tw_interrupt() *//* This function handles ioctls from userspace to the driver */int tw_ioctl(TW_Device_Extension *tw_dev, int request_id){ unsigned char opcode; int bufflen, error = 0; TW_Param *param; TW_Command *command_packet, *command_save; u32 param_value; TW_Ioctl *ioctl = NULL; TW_Passthru *passthru = NULL; int tw_aen_code, i, use_sg; char *data_ptr; int total_bytes = 0; ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer; if (ioctl == NULL) { printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Request buffer NULL.\n"); tw_dev->state[request_id] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, request_id); tw_dev->srb[request_id]->result = (DID_OK << 16); tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); return 0; } bufflen = tw_dev->srb[request_id]->request_bufflen; /* Initialize command packet */ command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; if (command_packet == NULL) { printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad command packet virtual address.\n"); tw_dev->state[request_id] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, request_id); tw_dev->srb[request_id]->result = (DID_OK << 16); tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); return 0; } memset(command_packet, 0, sizeof(TW_Sector)); /* Initialize param */ if (tw_dev->alignment_virtual_address[request_id] == NULL) { printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad alignment virtual address.\n"); tw_dev->state[request_id] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, request_id); tw_dev->srb[request_id]->result = (DID_OK << 16); tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); return 0; } param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; memset(param, 0, sizeof(TW_Sector)); dprintk(KERN_NOTICE "opcode = %d table_id = %d parameter_id = %d parameter_size_bytes = %d\n", ioctl->opcode, ioctl->table_id, ioctl->parameter_id, ioctl->parameter_size_bytes); opcode = ioctl->opcode; switch (opcode) { case TW_OP_NOP: dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_NOP.\n"); command_packet->byte0.opcode = TW_OP_NOP; break; case TW_OP_GET_PARAM: dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_GET_PARAM.\n"); command_packet->byte0.opcode = TW_OP_GET_PARAM; command_packet->byte3.unit = ioctl->unit_index; param->table_id = ioctl->table_id; param->parameter_id = ioctl->parameter_id; param->parameter_size_bytes = ioctl->parameter_size_bytes; tw_dev->ioctl_size[request_id] = ioctl->parameter_size_bytes; dprintk(KERN_NOTICE "table_id = %d parameter_id = %d parameter_size_bytes %d\n", param->table_id, param->parameter_id, param->parameter_size_bytes); break; case TW_OP_SET_PARAM: dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_SET_PARAM: table_id = %d, parameter_id = %d, parameter_size_bytes = %d.\n", ioctl->table_id, ioctl->parameter_id, ioctl->parameter_size_bytes); if (ioctl->data != NULL) { command_packet->byte0.opcode = TW_OP_SET_PARAM; param->table_id = ioctl->table_id; param->parameter_id = ioctl->parameter_id; param->parameter_size_bytes = ioctl->parameter_size_bytes; memcpy(param->data, ioctl->data, ioctl->parameter_size_bytes); break; } else { printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n"); return 1; } case TW_OP_AEN_LISTEN: dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_AEN_LISTEN.\n"); if (tw_dev->aen_head == tw_dev->aen_tail) { /* aen queue empty */ dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): Aen queue empty.\n"); tw_aen_code = TW_AEN_QUEUE_EMPTY; memcpy(tw_dev->srb[request_id]->request_buffer, &tw_aen_code, ioctl->parameter_size_bytes); } else { /* Copy aen queue entry to request buffer */ dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): Returning aen 0x%x\n", tw_dev->aen_queue[tw_dev->aen_head]); tw_aen_code = tw_dev->aen_queue[tw_dev->aen_head]; memcpy(tw_dev->srb[request_id]->request_buffer, &tw_aen_code, ioctl->parameter_size_bytes); if (tw_dev->aen_head == TW_Q_LENGTH - 1) { tw_dev->aen_head = TW_Q_START; } else { tw_dev->aen_head = tw_dev->aen_head + 1; } } tw_dev->state[request_id] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, request_id); tw_dev->srb[request_id]->result = (DID_OK << 16); tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); return 0; case TW_ATA_PASSTHRU: if (ioctl->data != NULL) { memcpy(command_packet, ioctl->data, sizeof(TW_Command)); command_packet->request_id = request_id; } else { printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n"); return 1; } passthru = (TW_Passthru *)tw_dev->command_packet_virtual_address[request_id]; passthru->sg_list[0].length = passthru->sector_count*512; if (passthru->sg_list[0].length > TW_MAX_PASSTHRU_BYTES) { printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Passthru size (%ld) too big.\n", passthru->sg_list[0].length); return 1; } passthru->sg_list[0].address = virt_to_bus(tw_dev->alignment_virtual_address[request_id]); tw_post_command_packet(tw_dev, request_id); return 0; case TW_CMD_PACKET: dprintk(KERN_WARNING "3w-xxxx: tw_ioctl(): caught TW_CMD_PACKET.\n"); if (ioctl->data != NULL) { memcpy(command_packet, ioctl->data, sizeof(TW_Command)); command_packet->request_id = request_id; tw_post_command_packet(tw_dev, request_id); return 0; } else { printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n"); return 1; } case TW_CMD_PACKET_WITH_DATA: dprintk(KERN_WARNING "3w-xxxx: tw_ioctl(): caught TW_CMD_PACKET_WITH_DATA.\n"); command_save = (TW_Command *)tw_dev->alignment_virtual_address[request_id]; if (command_save == NULL) { printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad alignment virtual address.\n", tw_dev->host->host_no); return 1; } if (ioctl->data != NULL) { /* Copy down the command packet */ memcpy(command_packet, ioctl->data, sizeof(TW_Command)); memcpy(command_save, ioctl->data, sizeof(TW_Command)); command_packet->request_id = request_id; /* Now deal with the two possible sglists */ if (command_packet->byte0.sgl_offset == 2) { use_sg = command_packet->size - 3; for (i=0;i<use_sg;i++) total_bytes+=command_packet->byte8.param.sgl[i].length; tw_dev->ioctl_data[request_id] = kmalloc(total_bytes, GFP_ATOMIC); if (!tw_dev->ioctl_data[request_id]) { printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): kmalloc failed for request_id %d.\n", tw_dev->host->host_no, request_id); return 1; } /* Copy param sglist into the kernel */ data_ptr = tw_dev->ioctl_data[request_id]; for (i=0;i<use_sg;i++) { if ((u32 *)command_packet->byte8.param.sgl[i].address != NULL) { error = copy_from_user(data_ptr, (u32 *)command_packet->byte8.param.sgl[i].address, command_packet->byte8.param.sgl[i].length); if (error) { printk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist from userspace.\n", tw_dev->host->host_no); goto tw_ioctl_bail; } } else { printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad param sgl address.\n", tw_dev->host->host_no); tw_dev->srb[request_id]->result = (DID_RESET << 16); goto tw_ioctl_bail; } data_ptr+=command_packet->byte8.param.sgl[i].length; } command_packet->size = 4; command_packet->byte8.param.sgl[0].address = virt_to_bus(tw_dev->ioctl_data[request_id]); command_packet->byte8.param.sgl[0].length = total_bytes; } if (command_packet->byte0.sgl_offset == 3) { use_sg = command_packet->size - 4; for (i=0;i<use_sg;i++) total_bytes+=command_packet->byte8.io.sgl[i].length; tw_dev->ioctl_data[request_id] = kmalloc(total_bytes, GFP_ATOMIC); if (!tw_dev->ioctl_data[request_id]) { printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): kmalloc failed for request_id %d.\n", tw_dev->host->host_no, request_id); return 1; } if (command_packet->byte0.opcode == TW_OP_WRITE) { /* Copy io sglist into the kernel */ data_ptr = tw_dev->ioctl_data[request_id]; for (i=0;i<use_sg;i++) { if ((u32 *)command_packet->byte8.io.sgl[i].address != NULL) { error = copy_from_user(data_ptr, (u32 *)command_packet->byte8.io.sgl[i].address, command_packet->byte8.io.sgl[i].length); if (error) { printk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist from userspace.\n", tw_dev->host->host_no); goto tw_ioctl_bail; } } else { printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad io sgl address.\n", tw_dev->host->host_no); tw_dev->srb[request_id]->result = (DID_RESET << 16); goto tw_ioctl_bail; } data_ptr+=command_packet->byte8.io.sgl[i].length; } } command_packet->size = 5; command_packet->byte8.io.sgl[0].address = virt_to_bus(tw_dev->ioctl_data[request_id]); command_packet->byte8.io.sgl[0].length = total_bytes; } spin_unlock_irq(&io_request_lock); spin_unlock_irq(&tw_dev->tw_lock); /* Finally post the command packet */ tw_post_command_packet(tw_dev, request_id); mdelay(TW_IOCTL_WAIT_TIME); spin_lock_irq(&tw_dev->tw_lock); spin_lock_irq(&io_request_lock); if (signal_pending(current)) { dprintk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Signal pending, aborting ioctl().\n", tw_dev->host->host_no); tw_dev->srb[request_id]->result = (DID_OK << 16); goto tw_ioctl_bail; } tw_dev->srb[request_id]->result = (DID_OK << 16); /* Now copy up the param or io sglist to userspace */ if (command_packet->byte0.sgl_offset == 2) { use_sg = command_save->size - 3; data_ptr = phys_to_virt(command_packet->byte8.param.sgl[0].address); for (i=0;i<use_sg;i++) { if ((u32 *)command_save->byte8.param.sgl[i].address != NULL) { error = copy_to_user((u32 *)command_save->byte8.param.sgl[i].address, data_ptr, command_save->byte8.param.sgl[i].length); if (error) { printk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist to userspace.\n", tw_dev->host->host_no); goto tw_ioctl_bail; } dprintk(KERN_WARNING "3w-xxxx: scsi%d: Copied %ld by
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -