"static int xxx_slave_alloc(struct scsi_device * sdev) { /* code */ }"
** the scsi_host_alloc() function is a replacement for the rather vaguely
-named scsi_register() function in most situations. The scsi_register()
-and scsi_unregister() functions remain to support legacy LLDs that use
-the passive initialization model.
+named scsi_register() function in most situations.
Hotplug initialization model
struct scsi_device instances are freed after slave_destroy().
-Passive initialization model
-============================
-These older LLDs include a file called "scsi_module.c" [yes the ".c" is a
-little surprising] in their source code. For that file to work an
-instance of struct scsi_host_template with the name "driver_template"
-needs to be defined. Here is a typical code sequence used in this model:
- static struct scsi_host_template driver_template = {
- ...
- };
- #include "scsi_module.c"
-
-The scsi_module.c file contains two functions:
- - init_this_scsi_driver() which is executed when the LLD is
- initialized (i.e. boot time or module load time)
- - exit_this_scsi_driver() which is executed when the LLD is shut
- down (i.e. module unload time)
-Note: since these functions are tagged with __init and __exit qualifiers
-an LLD should not call them explicitly (since the kernel does that).
-
-Here is an example of an initialization sequence when two hosts are
-detected (so detect() returns 2) and the SCSI bus scan on each host
-finds 1 SCSI device (and a second device does not respond).
-
-LLD mid level LLD
-===----------------------=========-----------------===------
-init_this_scsi_driver() ----+
- |
- detect() -----------------+
- | |
- | scsi_register()
- | scsi_register()
- |
- slave_alloc()
- slave_configure() --> scsi_change_queue_depth()
- slave_alloc() ***
- slave_destroy() ***
- |
- slave_alloc()
- slave_configure()
- slave_alloc() ***
- slave_destroy() ***
-------------------------------------------------------------
-
-The mid level invokes scsi_change_queue_depth() with "cmd_per_lun" for that
-host as the queue length. These settings can be overridden by a
-slave_configure() supplied by the LLD.
-
-*** For scsi devices that the mid level tries to scan but do not
- respond, a slave_alloc(), slave_destroy() pair is called.
-
-Here is an LLD shutdown sequence:
-
-LLD mid level LLD
-===----------------------=========-----------------===------
-exit_this_scsi_driver() ----+
- |
- slave_destroy()
- release() --> scsi_unregister()
- |
- slave_destroy()
- release() --> scsi_unregister()
-------------------------------------------------------------
-
-An LLD need not define slave_destroy() (i.e. it is optional).
-
-The shortcoming of the "passive initialization model" is that host
-registration and de-registration are (typically) tied to LLD initialization
-and shutdown. Once the LLD is initialized then a new host that appears
-(e.g. via hotplugging) cannot easily be added without a redundant
-driver shutdown and re-initialization. It may be possible to write an LLD
-that uses both initialization models.
-
-
Reference Counting
==================
The Scsi_Host structure has had reference counting infrastructure added.
Summary:
bios_param - fetch head, sector, cylinder info for a disk
- detect - detects HBAs this driver wants to control
eh_timed_out - notify the host that a command timer expired
eh_abort_handler - abort given command
eh_bus_reset_handler - issue SCSI bus reset
ioctl - driver can respond to ioctls
proc_info - supports /proc/scsi/{driver_name}/{host_no}
queuecommand - queue scsi command, invoke 'done' on completion
- release - release all resources associated with given host
slave_alloc - prior to any commands being sent to a new device
slave_configure - driver fine tuning for given device after attach
slave_destroy - given device is about to be shut down
sector_t capacity, int params[3])
-/**
- * detect - detects HBAs this driver wants to control
- * @shtp: host template for this driver.
- *
- * Returns number of hosts this driver wants to control. 0 means no
- * suitable hosts found.
- *
- * Locks: none held
- *
- * Calling context: process [invoked from init_this_scsi_driver()]
- *
- * Notes: First function called from the SCSI mid level on this
- * driver. Upper level drivers (e.g. sd) may not (yet) be present.
- * For each host found, this method should call scsi_register()
- * [see hosts.c].
- *
- * Defined in: LLD (required if "passive initialization mode" is used,
- * not invoked in "hotplug initialization mode")
- **/
- int detect(struct scsi_host_template * shtp)
-
-
/**
* eh_timed_out - The timer for the command has just fired
* @scp: identifies command timing out
int queuecommand(struct Scsi_Host *shost, struct scsi_cmnd * scp)
-/**
- * release - release all resources associated with given host
- * @shp: host to be released.
- *
- * Return value ignored (could soon be a function returning void).
- *
- * Locks: none held
- *
- * Calling context: process
- *
- * Notes: Invoked from scsi_module.c's exit_this_scsi_driver().
- * LLD's implementation of this function should call
- * scsi_unregister(shp) prior to returning.
- * Only needed for old-style host templates.
- *
- * Defined in: LLD (required in "passive initialization model",
- * should not be defined in hotplug model)
- **/
- int release(struct Scsi_Host * shp)
-
-
/**
* slave_alloc - prior to any commands being sent to a new device
* (i.e. just prior to scan) this call is made
+++ /dev/null
-/*
- * Copyright (C) 2003 Christoph Hellwig.
- * Released under GPL v2.
- *
- * Support for old-style host templates.
- *
- * NOTE: Do not use this for new drivers ever.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <scsi/scsi_host.h>
-
-
-static int __init init_this_scsi_driver(void)
-{
- struct scsi_host_template *sht = &driver_template;
- struct Scsi_Host *shost;
- struct list_head *l;
- int error;
-
- if (!sht->release) {
- printk(KERN_ERR
- "scsi HBA driver %s didn't set a release method.\n",
- sht->name);
- return -EINVAL;
- }
-
- sht->module = THIS_MODULE;
- INIT_LIST_HEAD(&sht->legacy_hosts);
-
- sht->detect(sht);
- if (list_empty(&sht->legacy_hosts))
- return -ENODEV;
-
- list_for_each_entry(shost, &sht->legacy_hosts, sht_legacy_list) {
- error = scsi_add_host(shost, NULL);
- if (error)
- goto fail;
- scsi_scan_host(shost);
- }
- return 0;
- fail:
- l = &shost->sht_legacy_list;
- while ((l = l->prev) != &sht->legacy_hosts)
- scsi_remove_host(list_entry(l, struct Scsi_Host, sht_legacy_list));
- return error;
-}
-
-static void __exit exit_this_scsi_driver(void)
-{
- struct scsi_host_template *sht = &driver_template;
- struct Scsi_Host *shost, *s;
-
- list_for_each_entry(shost, &sht->legacy_hosts, sht_legacy_list)
- scsi_remove_host(shost);
- list_for_each_entry_safe(shost, s, &sht->legacy_hosts, sht_legacy_list)
- sht->release(shost);
-
- if (list_empty(&sht->legacy_hosts))
- return;
-
- printk(KERN_WARNING "%s did not call scsi_unregister\n", sht->name);
- dump_stack();
-
- list_for_each_entry_safe(shost, s, &sht->legacy_hosts, sht_legacy_list)
- scsi_unregister(shost);
-}
-
-module_init(init_this_scsi_driver);
-module_exit(exit_this_scsi_driver);
struct module *module;
const char *name;
- /*
- * Used to initialize old-style drivers. For new-style drivers
- * just perform all work in your module initialization function.
- *
- * Status: OBSOLETE
- */
- int (* detect)(struct scsi_host_template *);
-
- /*
- * Used as unload callback for hosts with old-style drivers.
- *
- * Status: OBSOLETE
- */
- int (* release)(struct Scsi_Host *);
-
/*
* The info function will return whatever useful information the
* developer sees fit. If not provided, then the name field will
*/
const struct attribute_group **sdev_groups;
- /*
- * List of hosts per template.
- *
- * This is only for use by scsi_module.c for legacy templates.
- * For these access to it is synchronized implicitly by
- * module_init/module_exit.
- */
- struct list_head legacy_hosts;
-
/*
* Vendor Identifier associated with the host
*
/* ldm bits */
struct device shost_gendev, shost_dev;
- /*
- * List of hosts per template.
- *
- * This is only for use by scsi_module.c for legacy templates.
- * For these access to it is synchronized implicitly by
- * module_init/module_exit.
- */
- struct list_head sht_legacy_list;
-
/*
* Points to the transport data (if any) which is allocated
* separately
return shost->prot_guard_type;
}
-/* legacy interfaces */
-extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int);
-extern void scsi_unregister(struct Scsi_Host *);
extern int scsi_host_set_state(struct Scsi_Host *, enum scsi_host_state);
#endif /* _SCSI_SCSI_HOST_H */