drivers/usb/storage/usb.c

Source file repositories/reference/linux-study-clean/drivers/usb/storage/usb.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/storage/usb.c
Extension
.c
Size
33971 bytes
Lines
1259
Domain
Driver Families
Bucket
drivers/usb
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (srb == NULL) {
			scsi_unlock(host);
			mutex_unlock(&us->dev_mutex);
			usb_stor_dbg(us, "-- exiting\n");
			break;
		}

		/* has the command timed out *already* ? */
		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
			srb->result = DID_ABORT << 16;
			goto SkipForAbort;
		}

		scsi_unlock(host);

		/*
		 * reject the command if the direction indicator
		 * is UNKNOWN
		 */
		if (srb->sc_data_direction == DMA_BIDIRECTIONAL) {
			usb_stor_dbg(us, "UNKNOWN data direction\n");
			srb->result = DID_ERROR << 16;
		}

		/*
		 * reject if target != 0 or if LUN is higher than
		 * the maximum known LUN
		 */
		else if (srb->device->id &&
				!(us->fflags & US_FL_SCM_MULT_TARG)) {
			usb_stor_dbg(us, "Bad target number (%d:%llu)\n",
				     srb->device->id,
				     srb->device->lun);
			srb->result = DID_BAD_TARGET << 16;
		}

		else if (srb->device->lun > us->max_lun) {
			usb_stor_dbg(us, "Bad LUN (%d:%llu)\n",
				     srb->device->id,
				     srb->device->lun);
			srb->result = DID_BAD_TARGET << 16;
		}

		/*
		 * Handle those devices which need us to fake
		 * their inquiry data
		 */
		else if ((srb->cmnd[0] == INQUIRY) &&
			    (us->fflags & US_FL_FIX_INQUIRY)) {
			unsigned char data_ptr[36] = {
			    0x00, 0x80, 0x02, 0x02,
			    0x1F, 0x00, 0x00, 0x00};

			usb_stor_dbg(us, "Faking INQUIRY command\n");
			fill_inquiry_response(us, data_ptr, 36);
			srb->result = SAM_STAT_GOOD;
		}

		/* we've got a command, let's do it! */
		else {
			US_DEBUG(usb_stor_show_command(us, srb));
			us->proto_handler(srb, us);
			usb_mark_last_busy(us->pusb_dev);
		}

		/* lock access to the state */
		scsi_lock(host);

		/* was the command aborted? */
		if (srb->result == DID_ABORT << 16) {
SkipForAbort:
			usb_stor_dbg(us, "scsi command aborted\n");
			srb = NULL;	/* Don't call scsi_done() */
		}

		/*
		 * If an abort request was received we need to signal that
		 * the abort has finished.  The proper test for this is
		 * the TIMED_OUT flag, not srb->result == DID_ABORT, because
		 * the timeout might have occurred after the command had
		 * already completed with a different result code.
		 */
		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
			complete(&(us->notify));

			/* Allow USB transfers to resume */
			clear_bit(US_FLIDX_ABORTING, &us->dflags);
			clear_bit(US_FLIDX_TIMED_OUT, &us->dflags);
		}

Annotation

Implementation Notes