// SPDX-License-Identifier: GPL-2.0-or-later /* * * Linux MegaRAID device driver * * Copyright (c) 2003-2004 LSI Logic Corporation. * * FILE : megaraid_mbox.c * Version : v2.20.5.1 (Nov 16 2006) * * Authors: * Atul Mukker <[email protected]> * Sreenivas Bagalkote <[email protected]> * Manoj Jose <[email protected]> * Seokmann Ju * * List of supported controllers * * OEM Product Name VID DID SSVID SSID * --- ------------ --- --- ---- ---- * Dell PERC3/QC 101E 1960 1028 0471 * Dell PERC3/DC 101E 1960 1028 0493 * Dell PERC3/SC 101E 1960 1028 0475 * Dell PERC3/Di 1028 1960 1028 0123 * Dell PERC4/SC 1000 1960 1028 0520 * Dell PERC4/DC 1000 1960 1028 0518 * Dell PERC4/QC 1000 0407 1028 0531 * Dell PERC4/Di 1028 000F 1028 014A * Dell PERC 4e/Si 1028 0013 1028 016c * Dell PERC 4e/Di 1028 0013 1028 016d * Dell PERC 4e/Di 1028 0013 1028 016e * Dell PERC 4e/Di 1028 0013 1028 016f * Dell PERC 4e/Di 1028 0013 1028 0170 * Dell PERC 4e/DC 1000 0408 1028 0002 * Dell PERC 4e/SC 1000 0408 1028 0001 * * LSI MegaRAID SCSI 320-0 1000 1960 1000 A520 * LSI MegaRAID SCSI 320-1 1000 1960 1000 0520 * LSI MegaRAID SCSI 320-2 1000 1960 1000 0518 * LSI MegaRAID SCSI 320-0X 1000 0407 1000 0530 * LSI MegaRAID SCSI 320-2X 1000 0407 1000 0532 * LSI MegaRAID SCSI 320-4X 1000 0407 1000 0531 * LSI MegaRAID SCSI 320-1E 1000 0408 1000 0001 * LSI MegaRAID SCSI 320-2E 1000 0408 1000 0002 * LSI MegaRAID SATA 150-4 1000 1960 1000 4523 * LSI MegaRAID SATA 150-6 1000 1960 1000 0523 * LSI MegaRAID SATA 300-4X 1000 0409 1000 3004 * LSI MegaRAID SATA 300-8X 1000 0409 1000 3008 * * INTEL RAID Controller SRCU42X 1000 0407 8086 0532 * INTEL RAID Controller SRCS16 1000 1960 8086 0523 * INTEL RAID Controller SRCU42E 1000 0408 8086 0002 * INTEL RAID Controller SRCZCRX 1000 0407 8086 0530 * INTEL RAID Controller SRCS28X 1000 0409 8086 3008 * INTEL RAID Controller SROMBU42E 1000 0408 8086 3431 * INTEL RAID Controller SROMBU42E 1000 0408 8086 3499 * INTEL RAID Controller SRCU51L 1000 1960 8086 0520 * * FSC MegaRAID PCI Express ROMB 1000 0408 1734 1065 * * ACER MegaRAID ROMB-2E 1000 0408 1025 004D * * NEC MegaRAID PCI Express ROMB 1000 0408 1033 8287 * * For history of changes, see Documentation/scsi/ChangeLog.megaraid */ #include <linux/slab.h> #include <linux/module.h> #include "megaraid_mbox.h" static int megaraid_init(void); static void megaraid_exit(void); static int megaraid_probe_one(struct pci_dev*, const struct pci_device_id *); static void megaraid_detach_one(struct pci_dev *); static void megaraid_mbox_shutdown(struct pci_dev *); static int megaraid_io_attach(adapter_t *); static void megaraid_io_detach(adapter_t *); static int megaraid_init_mbox(adapter_t *); static void megaraid_fini_mbox(adapter_t *); static int megaraid_alloc_cmd_packets(adapter_t *); static void megaraid_free_cmd_packets(adapter_t *); static int megaraid_mbox_setup_dma_pools(adapter_t *); static void megaraid_mbox_teardown_dma_pools(adapter_t *); static int megaraid_sysfs_alloc_resources(adapter_t *); static void megaraid_sysfs_free_resources(adapter_t *); static int megaraid_abort_handler(struct scsi_cmnd *); static int megaraid_reset_handler(struct scsi_cmnd *); static int mbox_post_sync_cmd(adapter_t *, uint8_t []); static int mbox_post_sync_cmd_fast(adapter_t *, uint8_t []); static int megaraid_busywait_mbox(mraid_device_t *); static int megaraid_mbox_product_info(adapter_t *); static int megaraid_mbox_extended_cdb(adapter_t *); static int megaraid_mbox_support_ha(adapter_t *, uint16_t *); static int megaraid_mbox_support_random_del(adapter_t *); static int megaraid_mbox_get_max_sg(adapter_t *); static void megaraid_mbox_enum_raid_scsi(adapter_t *); static void megaraid_mbox_flush_cache(adapter_t *); static int megaraid_mbox_fire_sync_cmd(adapter_t *); static void megaraid_mbox_display_scb(adapter_t *, scb_t *); static void megaraid_mbox_setup_device_map(adapter_t *); static int megaraid_queue_command(struct Scsi_Host *, struct scsi_cmnd *); static scb_t *megaraid_mbox_build_cmd(adapter_t *, struct scsi_cmnd *, int *); static void megaraid_mbox_runpendq(adapter_t *, scb_t *); static void megaraid_mbox_prepare_pthru(adapter_t *, scb_t *, struct scsi_cmnd *); static void megaraid_mbox_prepare_epthru(adapter_t *, scb_t *, struct scsi_cmnd *); static irqreturn_t megaraid_isr(int, void *); static void megaraid_mbox_dpc(unsigned long); static ssize_t megaraid_mbox_app_hndl_show(struct device *, struct device_attribute *attr, char *); static ssize_t megaraid_mbox_ld_show(struct device *, struct device_attribute *attr, char *); static int megaraid_cmm_register(adapter_t *); static int megaraid_cmm_unregister(adapter_t *); static int megaraid_mbox_mm_handler(unsigned long, uioc_t *, uint32_t); static int megaraid_mbox_mm_command(adapter_t *, uioc_t *); static void megaraid_mbox_mm_done(adapter_t *, scb_t *); static int gather_hbainfo(adapter_t *, mraid_hba_info_t *); static int wait_till_fw_empty(adapter_t *); MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; MODULE_VERSION(…); /* * ### modules parameters for driver ### */ /* * Set to enable driver to expose unconfigured disk to kernel */ static int megaraid_expose_unconf_disks = …; module_param_named(unconf_disks, megaraid_expose_unconf_disks, int, 0); MODULE_PARM_DESC(…) …; /* * driver wait time if the adapter's mailbox is busy */ static unsigned int max_mbox_busy_wait = …; module_param_named(busy_wait, max_mbox_busy_wait, int, 0); MODULE_PARM_DESC(…) …; /* * number of sectors per IO command */ static unsigned int megaraid_max_sectors = …; module_param_named(max_sectors, megaraid_max_sectors, int, 0); MODULE_PARM_DESC(…) …; /* * number of commands per logical unit */ static unsigned int megaraid_cmd_per_lun = …; module_param_named(cmd_per_lun, megaraid_cmd_per_lun, int, 0); MODULE_PARM_DESC(…) …; /* * Fast driver load option, skip scanning for physical devices during load. * This would result in non-disk devices being skipped during driver load * time. These can be later added though, using /proc/scsi/scsi */ static unsigned int megaraid_fast_load; module_param_named(fast_load, megaraid_fast_load, int, 0); MODULE_PARM_DESC(…) …; /* * mraid_debug level - threshold for amount of information to be displayed by * the driver. This level can be changed through modules parameters, ioctl or * sysfs/proc interface. By default, print the announcement messages only. */ int mraid_debug_level = …; module_param_named(debug_level, mraid_debug_level, int, 0); MODULE_PARM_DESC(…) …; /* * PCI table for all supported controllers. */ static struct pci_device_id pci_id_table_g[] = …; MODULE_DEVICE_TABLE(pci, pci_id_table_g); static struct pci_driver megaraid_pci_driver = …; // definitions for the device attributes for exporting logical drive number // for a scsi address (Host, Channel, Id, Lun) static DEVICE_ATTR_ADMIN_RO(megaraid_mbox_app_hndl); // Host template initializer for megaraid mbox sysfs device attributes static struct attribute *megaraid_shost_attrs[] = …; ATTRIBUTE_GROUPS(…); static DEVICE_ATTR_ADMIN_RO(megaraid_mbox_ld); // Host template initializer for megaraid mbox sysfs device attributes static struct attribute *megaraid_sdev_attrs[] = …; ATTRIBUTE_GROUPS(…); /* * Scsi host template for megaraid unified driver */ static const struct scsi_host_template megaraid_template_g = …; /** * megaraid_init - module load hook * * We register ourselves as hotplug enabled module and let PCI subsystem * discover our adapters. */ static int __init megaraid_init(void) { … } /** * megaraid_exit - driver unload entry point * * We simply unwrap the megaraid_init routine here. */ static void __exit megaraid_exit(void) { … } /** * megaraid_probe_one - PCI hotplug entry point * @pdev : handle to this controller's PCI configuration space * @id : pci device id of the class of controllers * * This routine should be called whenever a new adapter is detected by the * PCI hotplug susbsystem. */ static int megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { … } /** * megaraid_detach_one - release framework resources and call LLD release routine * @pdev : handle for our PCI configuration space * * This routine is called during driver unload. We free all the allocated * resources and call the corresponding LLD so that it can also release all * its resources. * * This routine is also called from the PCI hotplug system. */ static void megaraid_detach_one(struct pci_dev *pdev) { … } /** * megaraid_mbox_shutdown - PCI shutdown for megaraid HBA * @pdev : generic driver model device * * Shutdown notification, perform flush cache. */ static void megaraid_mbox_shutdown(struct pci_dev *pdev) { … } /** * megaraid_io_attach - attach a device with the IO subsystem * @adapter : controller's soft state * * Attach this device with the IO subsystem. */ static int megaraid_io_attach(adapter_t *adapter) { … } /** * megaraid_io_detach - detach a device from the IO subsystem * @adapter : controller's soft state * * Detach this device from the IO subsystem. */ static void megaraid_io_detach(adapter_t *adapter) { … } /* * START: Mailbox Low Level Driver * * This is section specific to the single mailbox based controllers */ /** * megaraid_init_mbox - initialize controller * @adapter : our soft state * * - Allocate 16-byte aligned mailbox memory for firmware handshake * - Allocate controller's memory resources * - Find out all initialization data * - Allocate memory required for all the commands * - Use internal library of FW routines, build up complete soft state */ static int megaraid_init_mbox(adapter_t *adapter) { … } /** * megaraid_fini_mbox - undo controller initialization * @adapter : our soft state */ static void megaraid_fini_mbox(adapter_t *adapter) { … } /** * megaraid_alloc_cmd_packets - allocate shared mailbox * @adapter : soft state of the raid controller * * Allocate and align the shared mailbox. This mailbox is used to issue * all the commands. For IO based controllers, the mailbox is also registered * with the FW. Allocate memory for all commands as well. * This is our big allocator. */ static int megaraid_alloc_cmd_packets(adapter_t *adapter) { … } /** * megaraid_free_cmd_packets - free memory * @adapter : soft state of the raid controller * * Release memory resources allocated for commands. */ static void megaraid_free_cmd_packets(adapter_t *adapter) { … } /** * megaraid_mbox_setup_dma_pools - setup dma pool for command packets * @adapter : HBA soft state * * Setup the dma pools for mailbox, passthru and extended passthru structures, * and scatter-gather lists. */ static int megaraid_mbox_setup_dma_pools(adapter_t *adapter) { … } /** * megaraid_mbox_teardown_dma_pools - teardown dma pools for command packets * @adapter : HBA soft state * * Teardown the dma pool for mailbox, passthru and extended passthru * structures, and scatter-gather lists. */ static void megaraid_mbox_teardown_dma_pools(adapter_t *adapter) { … } /** * megaraid_alloc_scb - detach and return a scb from the free list * @adapter : controller's soft state * @scp : pointer to the scsi command to be executed * * Return the scb from the head of the free list. %NULL if there are none * available. */ static scb_t * megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp) { … } /** * megaraid_dealloc_scb - return the scb to the free pool * @adapter : controller's soft state * @scb : scb to be freed * * Return the scb back to the free list of scbs. The caller must 'flush' the * SCB before calling us. E.g., performing pci_unamp and/or pci_sync etc. * NOTE NOTE: Make sure the scb is not on any list before calling this * routine. */ static inline void megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb) { … } /** * megaraid_mbox_mksgl - make the scatter-gather list * @adapter : controller's soft state * @scb : scsi control block * * Prepare the scatter-gather list. */ static int megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) { … } /** * mbox_post_cmd - issue a mailbox command * @adapter : controller's soft state * @scb : command to be issued * * Post the command to the controller if mailbox is available. */ static int mbox_post_cmd(adapter_t *adapter, scb_t *scb) { … } /** * megaraid_queue_command_lck - generic queue entry point for all LLDs * @scp : pointer to the scsi command to be executed * * Queue entry point for mailbox based controllers. */ static int megaraid_queue_command_lck(struct scsi_cmnd *scp) { … } static DEF_SCSI_QCMD(megaraid_queue_command) /** * megaraid_mbox_build_cmd - transform the mid-layer scsi commands * @adapter : controller's soft state * @scp : mid-layer scsi command pointer * @busy : set if request could not be completed because of lack of * resources * * Transform the mid-layer scsi command to megaraid firmware lingua. * Convert the command issued by mid-layer to format understood by megaraid * firmware. We also complete certain commands without sending them to firmware. */ static scb_t * megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy) { … } /** * megaraid_mbox_runpendq - execute commands queued in the pending queue * @adapter : controller's soft state * @scb_q : SCB to be queued in the pending list * * Scan the pending list for commands which are not yet issued and try to * post to the controller. The SCB can be a null pointer, which would indicate * no SCB to be queue, just try to execute the ones in the pending list. * * NOTE: We do not actually traverse the pending list. The SCBs are plucked * out from the head of the pending list. If it is successfully issued, the * next SCB is at the head now. */ static void megaraid_mbox_runpendq(adapter_t *adapter, scb_t *scb_q) { … } /** * megaraid_mbox_prepare_pthru - prepare a command for physical devices * @adapter : pointer to controller's soft state * @scb : scsi control block * @scp : scsi command from the mid-layer * * Prepare a command for the scsi physical devices. */ static void megaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb, struct scsi_cmnd *scp) { … } /** * megaraid_mbox_prepare_epthru - prepare a command for physical devices * @adapter : pointer to controller's soft state * @scb : scsi control block * @scp : scsi command from the mid-layer * * Prepare a command for the scsi physical devices. This routine prepares * commands for devices which can take extended CDBs (>10 bytes). */ static void megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb, struct scsi_cmnd *scp) { … } /** * megaraid_ack_sequence - interrupt ack sequence for memory mapped HBAs * @adapter : controller's soft state * * Interrupt acknowledgement sequence for memory mapped HBAs. Find out the * completed command and put them on the completed list for later processing. * * Returns: 1 if the interrupt is valid, 0 otherwise */ static int megaraid_ack_sequence(adapter_t *adapter) { … } /** * megaraid_isr - isr for memory based mailbox based controllers * @irq : irq * @devp : pointer to our soft state * * Interrupt service routine for memory-mapped mailbox controllers. */ static irqreturn_t megaraid_isr(int irq, void *devp) { … } /** * megaraid_mbox_dpc - the tasklet to complete the commands from completed list * @devp : pointer to HBA soft state * * Pick up the commands from the completed list and send back to the owners. * This is a reentrant function and does not assume any locks are held while * it is being called. */ static void megaraid_mbox_dpc(unsigned long devp) { … } /** * megaraid_abort_handler - abort the scsi command * @scp : command to be aborted * * Abort a previous SCSI request. Only commands on the pending list can be * aborted. All the commands issued to the F/W must complete. **/ static int megaraid_abort_handler(struct scsi_cmnd *scp) { … } /** * megaraid_reset_handler - device reset handler for mailbox based driver * @scp : reference command * * Reset handler for the mailbox based controller. First try to find out if * the FW is still live, in which case the outstanding commands counter mut go * down to 0. If that happens, also issue the reservation reset command to * relinquish (possible) reservations on the logical drives connected to this * host. **/ static int megaraid_reset_handler(struct scsi_cmnd *scp) { … } /* * START: internal commands library * * This section of the driver has the common routine used by the driver and * also has all the FW routines */ /** * mbox_post_sync_cmd() - blocking command to the mailbox based controllers * @adapter : controller's soft state * @raw_mbox : the mailbox * * Issue a scb in synchronous and non-interrupt mode for mailbox based * controllers. */ static int mbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[]) { … } /** * mbox_post_sync_cmd_fast - blocking command to the mailbox based controllers * @adapter : controller's soft state * @raw_mbox : the mailbox * * Issue a scb in synchronous and non-interrupt mode for mailbox based * controllers. This is a faster version of the synchronous command and * therefore can be called in interrupt-context as well. */ static int mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[]) { … } /** * megaraid_busywait_mbox() - Wait until the controller's mailbox is available * @raid_dev : RAID device (HBA) soft state * * Wait until the controller's mailbox is available to accept more commands. * Wait for at most 1 second. */ static int megaraid_busywait_mbox(mraid_device_t *raid_dev) { … } /** * megaraid_mbox_product_info - some static information about the controller * @adapter : our soft state * * Issue commands to the controller to grab some parameters required by our * caller. */ static int megaraid_mbox_product_info(adapter_t *adapter) { … } /** * megaraid_mbox_extended_cdb - check for support for extended CDBs * @adapter : soft state for the controller * * This routine check whether the controller in question supports extended * ( > 10 bytes ) CDBs. */ static int megaraid_mbox_extended_cdb(adapter_t *adapter) { … } /** * megaraid_mbox_support_ha - Do we support clustering * @adapter : soft state for the controller * @init_id : ID of the initiator * * Determine if the firmware supports clustering and the ID of the initiator. */ static int megaraid_mbox_support_ha(adapter_t *adapter, uint16_t *init_id) { … } /** * megaraid_mbox_support_random_del - Do we support random deletion * @adapter : soft state for the controller * * Determine if the firmware supports random deletion. * Return: 1 is operation supported, 0 otherwise */ static int megaraid_mbox_support_random_del(adapter_t *adapter) { … } /** * megaraid_mbox_get_max_sg - maximum sg elements supported by the firmware * @adapter : soft state for the controller * * Find out the maximum number of scatter-gather elements supported by the * firmware. */ static int megaraid_mbox_get_max_sg(adapter_t *adapter) { … } /** * megaraid_mbox_enum_raid_scsi - enumerate the RAID and SCSI channels * @adapter : soft state for the controller * * Enumerate the RAID and SCSI channels for ROMB platforms so that channels * can be exported as regular SCSI channels. */ static void megaraid_mbox_enum_raid_scsi(adapter_t *adapter) { … } /** * megaraid_mbox_flush_cache - flush adapter and disks cache * @adapter : soft state for the controller * * Flush adapter cache followed by disks cache. */ static void megaraid_mbox_flush_cache(adapter_t *adapter) { … } /** * megaraid_mbox_fire_sync_cmd - fire the sync cmd * @adapter : soft state for the controller * * Clears the pending cmds in FW and reinits its RAID structs. */ static int megaraid_mbox_fire_sync_cmd(adapter_t *adapter) { … } /** * megaraid_mbox_display_scb - display SCB information, mostly debug purposes * @adapter : controller's soft state * @scb : SCB to be displayed * * Diplay information about the given SCB iff the current debug level is * verbose. */ static void megaraid_mbox_display_scb(adapter_t *adapter, scb_t *scb) { … } /** * megaraid_mbox_setup_device_map - manage device ids * @adapter : Driver's soft state * * Manage the device ids to have an appropriate mapping between the kernel * scsi addresses and megaraid scsi and logical drive addresses. We export * scsi devices on their actual addresses, whereas the logical drives are * exported on a virtual scsi channel. */ static void megaraid_mbox_setup_device_map(adapter_t *adapter) { … } /* * END: internal commands library */ /* * START: Interface for the common management module * * This is the module, which interfaces with the common management module to * provide support for ioctl and sysfs */ /** * megaraid_cmm_register - register with the management module * @adapter : HBA soft state * * Register with the management module, which allows applications to issue * ioctl calls to the drivers. This interface is used by the management module * to setup sysfs support as well. */ static int megaraid_cmm_register(adapter_t *adapter) { … } /** * megaraid_cmm_unregister - un-register with the management module * @adapter : HBA soft state * * Un-register with the management module. * FIXME: mgmt module must return failure for unregister if it has pending * commands in LLD. */ static int megaraid_cmm_unregister(adapter_t *adapter) { … } /** * megaraid_mbox_mm_handler - interface for CMM to issue commands to LLD * @drvr_data : LLD specific data * @kioc : CMM interface packet * @action : command action * * This routine is invoked whenever the Common Management Module (CMM) has a * command for us. The 'action' parameter specifies if this is a new command * or otherwise. */ static int megaraid_mbox_mm_handler(unsigned long drvr_data, uioc_t *kioc, uint32_t action) { … } /** * megaraid_mbox_mm_command - issues commands routed through CMM * @adapter : HBA soft state * @kioc : management command packet * * Issues commands, which are routed through the management module. */ static int megaraid_mbox_mm_command(adapter_t *adapter, uioc_t *kioc) { … } static int wait_till_fw_empty(adapter_t *adapter) { … } /** * megaraid_mbox_mm_done - callback for CMM commands * @adapter : HBA soft state * @scb : completed command * * Callback routine for internal commands originated from the management * module. */ static void megaraid_mbox_mm_done(adapter_t *adapter, scb_t *scb) { … } /** * gather_hbainfo - HBA characteristics for the applications * @adapter : HBA soft state * @hinfo : pointer to the caller's host info strucuture */ static int gather_hbainfo(adapter_t *adapter, mraid_hba_info_t *hinfo) { … } /* * END: Interface for the common management module */ /** * megaraid_sysfs_alloc_resources - allocate sysfs related resources * @adapter : controller's soft state * * Allocate packets required to issue FW calls whenever the sysfs attributes * are read. These attributes would require up-to-date information from the * FW. Also set up resources for mutual exclusion to share these resources and * the wait queue. * * Return 0 on success. * Return -ERROR_CODE on failure. */ static int megaraid_sysfs_alloc_resources(adapter_t *adapter) { … } /** * megaraid_sysfs_free_resources - free sysfs related resources * @adapter : controller's soft state * * Free packets allocated for sysfs FW commands */ static void megaraid_sysfs_free_resources(adapter_t *adapter) { … } /** * megaraid_sysfs_get_ldmap_done - callback for get ldmap * @uioc : completed packet * * Callback routine called in the ISR/tasklet context for get ldmap call */ static void megaraid_sysfs_get_ldmap_done(uioc_t *uioc) { … } /** * megaraid_sysfs_get_ldmap_timeout - timeout handling for get ldmap * @t : timed out timer * * Timeout routine to recover and return to application, in case the adapter * has stopped responding. A timeout of 60 seconds for this command seems like * a good value. */ static void megaraid_sysfs_get_ldmap_timeout(struct timer_list *t) { … } /** * megaraid_sysfs_get_ldmap - get update logical drive map * @adapter : controller's soft state * * This routine will be called whenever user reads the logical drive * attributes, go get the current logical drive mapping table from the * firmware. We use the management API's to issue commands to the controller. * * NOTE: The commands issuance functionality is not generalized and * implemented in context of "get ld map" command only. If required, the * command issuance logical can be trivially pulled out and implemented as a * standalone library. For now, this should suffice since there is no other * user of this interface. * * Return 0 on success. * Return -1 on failure. */ static int megaraid_sysfs_get_ldmap(adapter_t *adapter) { … } /** * megaraid_mbox_app_hndl_show - display application handle for this adapter * @dev : class device object representation for the host * @attr : device attribute (unused) * @buf : buffer to send data to * * Display the handle used by the applications while executing management * tasks on the adapter. We invoke a management module API to get the adapter * handle, since we do not interface with applications directly. */ static ssize_t megaraid_mbox_app_hndl_show(struct device *dev, struct device_attribute *attr, char *buf) { … } /** * megaraid_mbox_ld_show - display the logical drive number for this device * @dev : device object representation for the scsi device * @attr : device attribute to show * @buf : buffer to send data to * * Display the logical drive number for the device in question, if it a valid * logical drive. For physical devices, "-1" is returned. * * The logical drive number is displayed in following format: * * <SCSI ID> <LD NUM> <LD STICKY ID> <APP ADAPTER HANDLE> * * <int> <int> <int> <int> */ static ssize_t megaraid_mbox_ld_show(struct device *dev, struct device_attribute *attr, char *buf) { … } /* * END: Mailbox Low Level Driver */ module_init(…) …; module_exit(megaraid_exit);