Linux SCSI Disk Driver

Source: Internet
Author: User
Tags goto

Sd.c

Static void sd_config_discard (struct scsi_disk *, unsigned int); static void  sd_config_write_same (struct scsi_disk *); Static int  sd_revalidate_disk (struct  gendisk *); static void sd_unlock_native_capacity (struct gendisk *disk); static  int  sd_probe (struct device *); Static int  sd_remove (struct  device *); Static void sd_shutdown (struct device *); Static int sd_suspend ( struct device *); Static int sd_resume (struct device *); static void sd_ Rescan (struct device *); Static int sd_init_command (STRUCT SCSI_CMND *SCPNT); Static void sd_uninit_command (STRUCT SCSI_CMND *SCPNT); Static int sd_done (struct  scsi_cmnd *); Static int sd_eh_action (Struct scsi_cmnd *, int);static  Void sd_read_capacity (struct scsi_disk *sdkp, unsigned char *buffer); static void scsi_disk_ Release (Struct device *cdev); Static void sd_print_sense_hdr (struct scsi_disk *,  struct scsi_sense_hdr *); Static void sd_print_result (struct scsi_disk *,  int);
Module_init (INIT_SD);/** *init_sd - entry point for this driver  (both  when built in or when *a module) . * *note: this  Function registers this driver with the scsi mid-level. **/static  int __init init_sd (void) {int majors = 0, i, err; Scsi_log_hlqueue (3,&NBSP;PRINTK ("init_sd: sd driver entry point\n"));for  (i =  0; i < sd_majors; i++)          Register driver if   (Register_blkdev (Sd_major (i),  "SD")  == 0) majors++;if  (!majors) return -enodev; Err = class_register (&sd_disk_class);if  (err) goto err_out;sd_cdb_cache =  Kmem_cache_create ("sd_ext_cdb",  sd_ext_cdb_size, 0, 0, null);if  (!sd_cdb_cache)   {PRINTK (kern_err  "Sd: can ' T init extEnded cdb cache\n "); goto err_out_class;} Sd_cdb_pool = mempool_create_slab_pool (Sd_mempool_size, sd_cdb_cache);if  (!sd_cdb_pool) &NBSP;{PRINTK (kern_err  "Sd: can ' t init extended cdb pool\n"); goto err_out_ Cache;}          register the drive err = scsi_register_driver on the SCSI bus (&sd_ TEMPLATE.GENDRV);if  (Err) Goto err_out_driver;return 0;err_out_driver:mempool_destroy (sd_cdb_ Pool); Err_out_cache:kmem_cache_destroy (Sd_cdb_cache); Err_out_class:class_unregister (&sd_disk_class); err_ out:for  (i = 0; i < sd_majors; i++) Unregister_blkdev (Sd_major (i),  " SD "); return err;}
int scsi_register_driver (struct device_driver *drv) {Drv->bus = &scsi_bus_type;return driver_register (DRV);}

Sd_probe->async_schedule_domain (Sd_probe_async, SDKP, &scsi_sd_probe_domain);

Sd_probe_async->add_disk

Sd_revalidate_disk


Scsi_disk and Scsi_device can be obtained from Gendisk

struct Gendisk *disk

struct Scsi_disk *SDKP = scsi_disk (disk);

struct Scsi_device *SDP = sdkp->device;


Some interface functions:

static struct Scsi_disk *scsi_disk_get (struct gendisk *disk);

static struct Scsi_disk *scsi_disk_get_from_dev (struct device *dev);





Scsi_scan.c

Scsi_rescan_devicescsi_sysfs.cstatic Ssize_tstore_rescan_field (struct device *dev, struct device_attribute *attr, con St Char *buf, size_t count) {scsi_rescan_device (dev); return count;}

Scsi.c

Subsys_initcall (INIT_SCSI);

static int __init init_scsi (void) {int error;error = Scsi_init_queue (); if (error) Return error;error = Scsi_init_procfs (); if (error) Goto Cleanup_queue;error = Scsi_init_devinfo (); if (error) Goto Cleanup_procfs;error = Scsi_init_hosts (); if ( Error) Goto Cleanup_devlist;error = Scsi_init_sysctl (); if (error) Goto Cleanup_hosts;error = Scsi_sysfs_register (); if ( Error) Goto Cleanup_sysctl;scsi_netlink_init ();p RINTK (kern_notice "SCSI subsystem initialized\n"); return 0;cleanup_ Sysctl:scsi_exit_sysctl (); cleanup_hosts:scsi_exit_hosts (); Cleanup_devlist:scsi_exit_devinfo (); CLEANUP_PROCFS: Scsi_exit_procfs (); Cleanup_queue:scsi_exit_queue ();p RINTK (kern_err "SCSI subsystem failed to initialize, error =%d\n" ,-error); return error;}

Interface functions:

int scsi_device_get (struct scsi_device *sdev)


Scsi_sysfs.c

scsi_scan->scsi_scan_host_selected->scsi_scan_channel->__scsi_scan_target->scsi_probe_and_add_lun- >scsi_probe_lun->scsi_execute_req->scsi_execute_req_flags->scsi_execute->blk_execute_rq->blk _execute_rq_nowait->

__elv_add_request (q, RQ, where);

__blk_run_queue (q);->


/**

* __blk_run_queue_uncond-run a queue whether or not it has been stopped

* @q:the queue to run

*

* Description:

* Invoke request handling on a queue if there is any pending requests.

* May is used to restart request handling after a request have completed.

* This variant runs the ' queue whether or not ' the queue has been

* Stopped. Must is called with the queue lock held and interrupts

* Disabled. See also @blk_run_queue.

*/

inline void __blk_run_queue_uncond (struct request_queue *q)

{

if (Unlikely (Blk_queue_dead (q)))

Return


/*

* Some REQUEST_FN implementations, e.g. SCSI_REQUEST_FN (), Unlock

* The queue lock internally. As a result multiple threads may

* Running such a request function concurrently. Keep track of the

* Number of active REQUEST_FN invocations such that Blk_drain_queue ()

* Can wait until all these REQUEST_FN calls has finished.

*/

q->request_fn_active++;

Q->REQUEST_FN (q);

q->request_fn_active--;

}


Scsi_request_fn->scsi_dispatch_cmd->


/**

* Scsi_dispatch_command-dispatch a command to the low-level driver.

* @cmd: Command block we are dispatching.

*

* Return:nonzero Return request was rejected and device ' s queue needs to be

* Plugged.

*/

int scsi_dispatch_cmd (struct scsi_cmnd *cmd)

{

struct Scsi_host *host = cmd->device->host;

int RTN = 0;


Atomic_inc (&CMD->DEVICE->IOREQUEST_CNT);


/* Check if the device is still usable */

if (unlikely (cmd->device->sdev_state = = Sdev_del)) {

/* In Sdev_del we error all commands. Did_no_connect

* Returns an immediate error upwards, and signals

* The device is no longer present */

Cmd->result = Did_no_connect << 16;

Scsi_done (CMD);

/* return 0 (because the command has been processed) */

Goto out;

}


/* Check to see if the SCSI LLD made this device blocked. */

if (Unlikely (scsi_device_blocked (Cmd->device))) {

/*

* In blocked state, the command was just put back on

* the device queue. The suspend state has already

* Blocked the queue so future requests should not

* occur until the device transitions out of the

* Suspend state.

*/


Scsi_queue_insert (cmd, scsi_mlqueue_device_busy);


Scsi_log_mlqueue (3, PRINTK ("Queuecommand:device blocked \ n"));


/*

* Note:rtn is still zero here because we don ' t need the

* Queue to being plugged on return (it ' s already stopped)

*/

Goto out;

}


/*

* If SCSI-2 or lower, store the LUN value in Cmnd.

*/

if (cmd->device->scsi_level <= scsi_2 &&

Cmd->device->scsi_level! = Scsi_unknown) {

CMD->CMND[1] = (cmd->cmnd[1] & 0x1f) |

(Cmd->device->lun << 5 & 0XE0);

}


Scsi_log_send (CMD);


/*

* Before we queue this command, check if the command

* Length exceeds what the host adapter can handle.

*/

if (Cmd->cmd_len > Cmd->device->host->max_cmd_len) {

Scsi_log_mlqueue (3,

PRINTK ("Queuecommand:command too long."

"Cdb_size=%d host->max_cmd_len=%d\n",

Cmd->cmd_len, Cmd->device->host->max_cmd_len));

Cmd->result = (Did_abort << 16);


Scsi_done (CMD);

Goto out;

}


if (unlikely (host->shost_state = = Shost_del)) {

Cmd->result = (did_no_connect << 16);

Scsi_done (CMD);

} else {

Trace_scsi_dispatch_cmd_start (CMD);

Cmd->scsi_done = Scsi_done;

RTN = Host->hostt->queuecommand (host, CMD);

The CMD is routed through the host. such as FC, IB (SRP)

}


if (RTN) {

Trace_scsi_dispatch_cmd_error (cmd, RTN);

if (RTN! = Scsi_mlqueue_device_busy &&

Rtn! = scsi_mlqueue_target_busy)

RTN = Scsi_mlqueue_host_busy;


Scsi_queue_insert (cmd, RTN);


Scsi_log_mlqueue (3,

PRINTK ("Queuecommand:request rejected\n"));

}


Out

Scsi_log_mlqueue (3, PRINTK ("Leaving scsi_dispatch_cmnd () \ n"));

return RTN;

}



/* * create the actual show/store functions and data structures.  */static ssize_tstore_scan (struct device *dev, struct device_attribute * Attr,   const char *buf, size_t count) {Struct scsi_host *shost  = class_to_shost (dev); Int res;res = scsi_scan (SHOST,&NBSP;BUF);if  (res ==  0) res = count;return res;}; Static int scsi_scan (struct scsi_host *shost, const char *str) {CHAR&NBSP;S1 [15], s2[15], s3[15], junk;unsigned int channel, id, lun;int res;res &NBSP;=&NBSP;SSCANF (str,  "%10s %10s %10s %c",  s1, s2, s3, &junk); if  (res != 3) return -einval;if  (Check_set (&AMP;CHANNEL,&NBSP;S1)) return -EINVAL; if  (Check_set (&AMP;ID,&NBSP;S2)) return -einval;if  (Check_set (&lUN,&NBSP;S3)) return -einval;if  (Shost->transportt->user_scan) res = shost-> Transportt->user_scan (Shost, channel, id, lun); Elseres = scsi_scan_host_selected ( shost, channel, id, lun, 1); return res;}


Linux SCSI Disk Driver

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.