📄 csk_udisk_mgr.c
字号:
/* fill and submit the URB */ usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe, (unsigned char*) us->cr, data, size, usb_stor_blocking_completion, NULL); status = usb_stor_msg_common(us, timeout); /* return the actual length of the data transferred if no error */ if (status == 0) status = us->current_urb->actual_length; return status;}/* This is the common part of the URB message submission code * * All URBs from the usb-storage driver involved in handling a queued scsi * command _must_ pass through this function (or something like it) for the * abort mechanisms to work properly. */static int usb_stor_msg_common(struct us_data *us, int timeout){ struct completion urb_done; long timeleft; int status; /* don't submit URBs during abort/disconnect processing */ if (us->flags & ABORTING_OR_DISCONNECTING) return -EIO; /* set up data structures for the wakeup system */ init_completion(&urb_done); /* fill the common fields in the URB */ us->current_urb->context = &urb_done; us->current_urb->actual_length = 0; us->current_urb->error_count = 0; us->current_urb->status = 0; us->current_urb->transfer_flags = URB_NO_SETUP_DMA_MAP; if (us->current_urb->transfer_buffer == us->iobuf) us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; us->current_urb->transfer_dma = us->iobuf_dma; us->current_urb->setup_dma = us->cr_dma; /* submit the URB */ status = usb_submit_urb(us->current_urb, GFP_NOIO); if (status) { /* something went wrong */ return status; } /* since the URB has been submitted successfully, it's now okay * to cancel it */ set_bit(US_FLIDX_URB_ACTIVE, &us->flags); /* did an abort/disconnect occur during the submission? */ if (us->flags & ABORTING_OR_DISCONNECTING) { /* cancel the URB, if it hasn't been cancelled already */ if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) { usb_unlink_urb(us->current_urb); } } /* wait for the completion of the URB */ timeleft = wait_for_completion_interruptible_timeout( &urb_done, timeout ? : MAX_SCHEDULE_TIMEOUT); clear_bit(US_FLIDX_URB_ACTIVE, &us->flags); if (timeleft <= 0) { usb_kill_urb(us->current_urb); } /* return the URB status */ return us->current_urb->status;}/* * Interpret the results of a URB transfer * * This function prints appropriate debugging messages, clears halts on * non-control endpoints, and translates the status to the corresponding * USB_STOR_XFER_xxx return code. */static int interpret_urb_result(struct us_data *us, unsigned int pipe, unsigned int length, int result, unsigned int partial){ switch (result) { /* no error code; did we send all the data? */ case 0: if (partial != length) { return USB_STOR_XFER_SHORT; } return USB_STOR_XFER_GOOD; /* stalled */ case -EPIPE: /* for control endpoints, (used by CB[I]) a stall indicates * a failed command */ if (usb_pipecontrol(pipe)) { return USB_STOR_XFER_STALLED; } /* for other sorts of endpoint, clear the stall */ if (usb_stor_clear_halt(us, pipe) < 0) return USB_STOR_XFER_ERROR; return USB_STOR_XFER_STALLED; /* babble - the device tried to send more than we wanted to read */ case -EOVERFLOW: return USB_STOR_XFER_LONG; /* the transfer was cancelled by abort, disconnect, or timeout */ case -ECONNRESET: return USB_STOR_XFER_ERROR; /* short scatter-gather read transfer */ case -EREMOTEIO: return USB_STOR_XFER_SHORT; /* abort or disconnect in progress */ case -EIO: return USB_STOR_XFER_ERROR; /* the catch-all error case */ default: return USB_STOR_XFER_ERROR; }}static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, struct scatterlist *sg, int num_sg, unsigned int length, unsigned int *act_len){ int result; /* don't submit s-g requests during abort/disconnect processing */ if (us->flags & ABORTING_OR_DISCONNECTING) return USB_STOR_XFER_ERROR; /* initialize the scatter-gather request block */ result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0, sg, num_sg, length, GFP_NOIO); if (result) { return USB_STOR_XFER_ERROR; } /* since the block has been initialized successfully, it's now * okay to cancel it */ set_bit(US_FLIDX_SG_ACTIVE, &us->flags); /* did an abort/disconnect occur during the submission? */ if (us->flags & ABORTING_OR_DISCONNECTING) { /* cancel the request, if it hasn't been cancelled already */ if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) { usb_sg_cancel(&us->current_sg); } } /* wait for the completion of the transfer */ usb_sg_wait(&us->current_sg); clear_bit(US_FLIDX_SG_ACTIVE, &us->flags); result = us->current_sg.status; if (act_len) *act_len = us->current_sg.bytes; return interpret_urb_result(us, pipe, length, result, us->current_sg.bytes);}/* Determine what the maximum LUN supported is */static int usb_stor_Bulk_max_lun(struct us_data *us){ int result; /* issue the command */ us->iobuf[0] = 0; result = usb_stor_control_msg(us, us->recv_ctrl_pipe, US_BULK_GET_MAX_LUN, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, us->iobuf, 1, HZ); /* if we have a successful request, return the result */ if (result > 0) return us->iobuf[0]; if (result == -EPIPE) { usb_stor_clear_halt(us, us->recv_bulk_pipe); usb_stor_clear_halt(us, us->send_bulk_pipe); } return 0;}static void usb_stor_blocking_completion(struct urb *urb){ struct completion *urb_done_ptr = (struct completion *)urb->context; complete(urb_done_ptr);}/* Output routine for the sysfs max_sectors file */static ssize_t show_max_sectors(struct device *dev, struct device_attribute *attr, char *buf){ struct scsi_device *sdev = to_scsi_device(dev); printk("show_max_sectors:%u\n",sdev->request_queue->max_sectors); return sprintf(buf, "%u\n", sdev->request_queue->max_sectors);}/* Input routine for the sysfs max_sectors file */static ssize_t store_max_sectors(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct scsi_device *sdev = to_scsi_device(dev); unsigned short ms; if (sscanf(buf, "%hu", &ms) > 0 && ms <= SCSI_DEFAULT_MAX_SECTORS) { blk_queue_max_sectors(sdev->request_queue, ms); return strlen(buf); } return -EINVAL; }static int proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout){ struct us_data *us = host_to_us(host); char *pos = buffer; const char *string; /* if someone is sending us data, just throw it away */ if (inout) return length; /* print the controller name */ SPRINTF(" Host scsi%d: usb-storage\n", host->host_no); string = us->pusb_dev->manufacturer; SPRINTF(" Vendor: %s\n", string); string = us->pusb_dev->product; SPRINTF(" Product: %s\n", string); string = "None"; SPRINTF("Serial Number: %s\n", string); /* show the protocol and transport */ /* show the device flags */ if (pos < buffer + length) { pos += sprintf(pos, " Quirks:"); *(pos++) = '\n'; } /* * Calculate start of next buffer, and return value. */ *start = buffer + offset; if ((pos - buffer) < offset) return (0); else if ((pos - buffer - offset) < length) return (pos - buffer - offset); else return (length);}static const char* host_info(struct Scsi_Host *host){ return "SCSI emulation for SAMSUNG mobile";}static int queuecommand(struct scsi_cmnd *srb, void (*done)(struct scsi_cmnd *)){ struct us_data *us = host_to_us(srb->device->host); if (us->srb != NULL) { printk(KERN_ERR "Error in %s: us->srb = %p\n", __FUNCTION__, us->srb); return SCSI_MLQUEUE_HOST_BUSY; } if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { srb->result = DID_NO_CONNECT << 16; done(srb); return 0; } /* enqueue the command and wake up the control thread */ srb->scsi_done = done; us->srb = srb; up(&(us->sema)); return 0;}static int command_abort(struct scsi_cmnd *srb){ struct us_data *us = host_to_us(srb->device->host); scsi_lock(us_to_host(us)); /* Is this command still active? */ if (us->srb != srb) { scsi_unlock(us_to_host(us)); return FAILED; } set_bit(US_FLIDX_TIMED_OUT, &us->flags); if (!test_bit(US_FLIDX_RESETTING, &us->flags)) { set_bit(US_FLIDX_ABORTING, &us->flags); usb_stor_stop_transport(us); } scsi_unlock(us_to_host(us)); /* Wait for the aborted command to finish */ wait_for_completion(&us->notify); return SUCCESS;}static int device_reset(struct scsi_cmnd *srb){ struct us_data *us = host_to_us(srb->device->host); int result; /* lock the device pointers and do the reset */ mutex_lock(&(us->dev_mutex)); result = usb_stor_Bulk_reset(us); mutex_unlock(&us->dev_mutex); return result < 0 ? FAILED : SUCCESS;}/* Simulate a SCSI bus reset by resetting the device's USB port. */static int bus_reset(struct scsi_cmnd *srb){ struct us_data *us = host_to_us(srb->device->host); int result; result = usb_stor_port_reset(us); return result < 0 ? FAILED : SUCCESS;}static int slave_alloc (struct scsi_device *sdev){ struct us_data *us = host_to_us(sdev->host); sdev->inquiry_len = 36; return 0;}static int slave_configure(struct scsi_device *sdev){ struct us_data *us = host_to_us(sdev->host); blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); if (sdev->scsi_level < SCSI_2) sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2; if ((us->flags & US_FL_MAX_SECTORS_64) && sdev->request_queue->max_sectors > 64) blk_queue_max_sectors(sdev->request_queue, 64); if (sdev->type == TYPE_DISK) { sdev->use_10_for_ms = 1; sdev->use_192_bytes_for_3f = 1; if (us->flags & US_FL_NO_WP_DETECT) sdev->skip_ms_page_3f = 1; sdev->skip_ms_page_8 = 1; if (us->flags & US_FL_FIX_CAPACITY) sdev->fix_capacity = 1; sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2; sdev->retry_hwerror = 1; } else { sdev->use_10_for_ms = 1; } if (us->flags & US_FL_NOT_LOCKABLE) sdev->lockable = 0; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -