/* * dc395x.c * * Device Driver for Tekram DC395(U/UW/F), DC315(U) * PCI SCSI Bus Master Host Adapter * (SCSI chip set used Tekram ASIC TRM-S1040) * * Authors: * C.L. Huang <[email protected]> * Erich Chen <[email protected]> * (C) Copyright 1995-1999 Tekram Technology Co., Ltd. * * Kurt Garloff <[email protected]> * (C) 1999-2000 Kurt Garloff * * Oliver Neukum <[email protected]> * Ali Akcaagac <[email protected]> * Jamie Lenehan <[email protected]> * (C) 2003 * * License: GNU GPL * ************************************************************************* * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ************************************************************************ */ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/delay.h> #include <linux/ctype.h> #include <linux/blkdev.h> #include <linux/interrupt.h> #include <linux/init.h> #include <linux/spinlock.h> #include <linux/pci.h> #include <linux/list.h> #include <linux/vmalloc.h> #include <linux/slab.h> #include <asm/io.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> #include <scsi/scsi_transport_spi.h> #include "dc395x.h" #define DC395X_NAME … #define DC395X_BANNER … #define DC395X_VERSION … /*--------------------------------------------------------------------------- Features ---------------------------------------------------------------------------*/ /* * Set to disable parts of the driver */ /*#define DC395x_NO_DISCONNECT*/ /*#define DC395x_NO_TAGQ*/ /*#define DC395x_NO_SYNC*/ /*#define DC395x_NO_WIDE*/ /*--------------------------------------------------------------------------- Debugging ---------------------------------------------------------------------------*/ /* * Types of debugging that can be enabled and disabled */ #define DBG_KG … #define DBG_0 … #define DBG_1 … #define DBG_SG … #define DBG_FIFO … #define DBG_PIO … /* * Set set of things to output debugging for. * Undefine to remove all debugging */ /*#define DEBUG_MASK (DBG_0|DBG_1|DBG_SG|DBG_FIFO|DBG_PIO)*/ /*#define DEBUG_MASK DBG_0*/ /* * Output a kernel mesage at the specified level and append the * driver name and a ": " to the start of the message */ #define dprintkl(level, format, arg...) … #ifdef DEBUG_MASK /* * print a debug message - this is formated with KERN_DEBUG, then the * driver name followed by a ": " and then the message is output. * This also checks that the specified debug level is enabled before * outputing the message */ #define dprintkdbg … /* * Check if the specified type of debugging is enabled */ #define debug_enabled … #else /* * No debugging. Do nothing */ #define dprintkdbg(type, format, arg...) … #define debug_enabled(type) … #endif #ifndef PCI_VENDOR_ID_TEKRAM #define PCI_VENDOR_ID_TEKRAM … #endif #ifndef PCI_DEVICE_ID_TEKRAM_TRMS1040 #define PCI_DEVICE_ID_TEKRAM_TRMS1040 … #endif #define DC395x_LOCK_IO(dev,flags) … #define DC395x_UNLOCK_IO(dev,flags) … #define DC395x_read8(acb,address) … #define DC395x_read16(acb,address) … #define DC395x_read32(acb,address) … #define DC395x_write8(acb,address,value) … #define DC395x_write16(acb,address,value) … #define DC395x_write32(acb,address,value) … #define TAG_NONE … /* * srb->segement_x is the hw sg list. It is always allocated as a * DC395x_MAX_SG_LISTENTRY entries in a linear block which does not * cross a page boundy. */ #define SEGMENTX_LEN … struct SGentry { … }; /* The SEEPROM structure for TRM_S1040 */ struct NVRamTarget { … }; struct NvRamType { … }; struct ScsiReqBlk { … }; struct DeviceCtlBlk { … }; struct AdapterCtlBlk { … }; /*--------------------------------------------------------------------------- Forward declarations ---------------------------------------------------------------------------*/ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status); static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status); static void command_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status); static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status); static void msgout_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status); static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status); static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status); static void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status); static void command_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status); static void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status); static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status); static void msgin_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status); static void nop0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status); static void nop1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status); static void set_basic_config(struct AdapterCtlBlk *acb); static void cleanup_after_transfer(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb); static void reset_scsi_bus(struct AdapterCtlBlk *acb); static void data_io_transfer(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 io_dir); static void disconnect(struct AdapterCtlBlk *acb); static void reselect(struct AdapterCtlBlk *acb); static u8 start_scsi(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb); static inline void enable_msgout_abort(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb); static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb); static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_code, struct scsi_cmnd *cmd, u8 force); static void scsi_reset_detect(struct AdapterCtlBlk *acb); static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb); static void pci_unmap_srb_sense(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb); static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb); static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb); static void set_xfer_rate(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb); static void waiting_timeout(struct timer_list *t); /*--------------------------------------------------------------------------- Static Data ---------------------------------------------------------------------------*/ static u16 current_sync_offset = …; static void *dc395x_scsi_phase0[] = …; static void *dc395x_scsi_phase1[] = …; /* *Fast20: 000 50ns, 20.0 MHz * 001 75ns, 13.3 MHz * 010 100ns, 10.0 MHz * 011 125ns, 8.0 MHz * 100 150ns, 6.6 MHz * 101 175ns, 5.7 MHz * 110 200ns, 5.0 MHz * 111 250ns, 4.0 MHz * *Fast40(LVDS): 000 25ns, 40.0 MHz * 001 50ns, 20.0 MHz * 010 75ns, 13.3 MHz * 011 100ns, 10.0 MHz * 100 125ns, 8.0 MHz * 101 150ns, 6.6 MHz * 110 175ns, 5.7 MHz * 111 200ns, 5.0 MHz */ /*static u8 clock_period[] = {12,19,25,31,37,44,50,62};*/ /* real period:48ns,76ns,100ns,124ns,148ns,176ns,200ns,248ns */ static u8 clock_period[] = …; static u16 clock_speed[] = …; /*--------------------------------------------------------------------------- Configuration ---------------------------------------------------------------------------*/ /* * Module/boot parameters currently effect *all* instances of the * card in the system. */ /* * Command line parameters are stored in a structure below. * These are the index's into the structure for the various * command line options. */ #define CFG_ADAPTER_ID … #define CFG_MAX_SPEED … #define CFG_DEV_MODE … #define CFG_ADAPTER_MODE … #define CFG_TAGS … #define CFG_RESET_DELAY … #define CFG_NUM … /* * Value used to indicate that a command line override * hasn't been used to modify the value. */ #define CFG_PARAM_UNSET … /* * Hold command line parameters. */ struct ParameterData { … }; static struct ParameterData cfg_data[] = …; /* * Safe settings. If set to zero the BIOS/default values with * command line overrides will be used. If set to 1 then safe and * slow settings will be used. */ static bool use_safe_settings = …; module_param_named(safe, use_safe_settings, bool, 0); MODULE_PARM_DESC(…) …; module_param_named(adapter_id, cfg_data[CFG_ADAPTER_ID].value, int, 0); MODULE_PARM_DESC(…) …; module_param_named(max_speed, cfg_data[CFG_MAX_SPEED].value, int, 0); MODULE_PARM_DESC(…) …; module_param_named(dev_mode, cfg_data[CFG_DEV_MODE].value, int, 0); MODULE_PARM_DESC(…) …; module_param_named(adapter_mode, cfg_data[CFG_ADAPTER_MODE].value, int, 0); MODULE_PARM_DESC(…) …; module_param_named(tags, cfg_data[CFG_TAGS].value, int, 0); MODULE_PARM_DESC(…) …; module_param_named(reset_delay, cfg_data[CFG_RESET_DELAY].value, int, 0); MODULE_PARM_DESC(…) …; /** * set_safe_settings - if the use_safe_settings option is set then * set all values to the safe and slow values. **/ static void set_safe_settings(void) { … } /** * fix_settings - reset any boot parameters which are out of range * back to the default values. **/ static void fix_settings(void) { … } /* * Mapping from the eeprom delay index value (index into this array) * to the number of actual seconds that the delay should be for. */ static char eeprom_index_to_delay_map[] = …; /** * eeprom_index_to_delay - Take the eeprom delay setting and convert it * into a number of seconds. * * @eeprom: The eeprom structure in which we find the delay index to map. **/ static void eeprom_index_to_delay(struct NvRamType *eeprom) { … } /** * delay_to_eeprom_index - Take a delay in seconds and return the * closest eeprom index which will delay for at least that amount of * seconds. * * @delay: The delay, in seconds, to find the eeprom index for. **/ static int delay_to_eeprom_index(int delay) { … } /** * eeprom_override - Override the eeprom settings, in the provided * eeprom structure, with values that have been set on the command * line. * * @eeprom: The eeprom data to override with command line options. **/ static void eeprom_override(struct NvRamType *eeprom) { … } /*--------------------------------------------------------------------------- ---------------------------------------------------------------------------*/ static unsigned int list_size(struct list_head *head) { … } static struct DeviceCtlBlk *dcb_get_next(struct list_head *head, struct DeviceCtlBlk *pos) { … } static void free_tag(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { … } /* Find cmd in SRB list */ static inline struct ScsiReqBlk *find_cmd(struct scsi_cmnd *cmd, struct list_head *head) { … } /* Sets the timer to wake us up */ static void waiting_set_timer(struct AdapterCtlBlk *acb, unsigned long to) { … } /* Send the next command from the waiting list to the bus */ static void waiting_process_next(struct AdapterCtlBlk *acb) { … } /* Wake up waiting queue */ static void waiting_timeout(struct timer_list *t) { … } /* Get the DCB for a given ID/LUN combination */ static struct DeviceCtlBlk *find_dcb(struct AdapterCtlBlk *acb, u8 id, u8 lun) { … } /* Send SCSI Request Block (srb) to adapter (acb) */ static void send_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { … } /* Prepare SRB for being sent to Device DCB w/ command *cmd */ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { … } /** * dc395x_queue_command_lck - queue scsi command passed from the mid * layer, invoke 'done' on completion * * @cmd: pointer to scsi command object * * Returns 1 if the adapter (host) is busy, else returns 0. One * reason for an adapter to be busy is that the number * of outstanding queued commands is already equal to * struct Scsi_Host::can_queue . * * Required: if struct Scsi_Host::can_queue is ever non-zero * then this function is required. * * Locks: struct Scsi_Host::host_lock held on entry (with "irqsave") * and is expected to be held on return. * */ static int dc395x_queue_command_lck(struct scsi_cmnd *cmd) { … } static DEF_SCSI_QCMD(dc395x_queue_command) static void dump_register_info(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { … } static inline void clear_fifo(struct AdapterCtlBlk *acb, char *txt) { … } static void reset_dev_param(struct AdapterCtlBlk *acb) { … } /* * perform a hard reset on the SCSI bus * @cmd - some command for this host (for fetching hooks) * Returns: SUCCESS (0x2002) on success, else FAILED (0x2003). */ static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd) { … } static int dc395x_eh_bus_reset(struct scsi_cmnd *cmd) { … } /* * abort an errant SCSI command * @cmd - command to be aborted * Returns: SUCCESS (0x2002) on success, else FAILED (0x2003). */ static int dc395x_eh_abort(struct scsi_cmnd *cmd) { … } /* SDTR */ static void build_sdtr(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { … } /* WDTR */ static void build_wdtr(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { … } #if 0 /* Timer to work around chip flaw: When selecting and the bus is * busy, we sometimes miss a Selection timeout IRQ */ void selection_timeout_missed(unsigned long ptr); /* Sets the timer to wake us up */ static void selto_timer(struct AdapterCtlBlk *acb) { if (timer_pending(&acb->selto_timer)) return; acb->selto_timer.function = selection_timeout_missed; acb->selto_timer.data = (unsigned long) acb; if (time_before (jiffies + HZ, acb->last_reset + HZ / 2)) acb->selto_timer.expires = acb->last_reset + HZ / 2 + 1; else acb->selto_timer.expires = jiffies + HZ + 1; add_timer(&acb->selto_timer); } void selection_timeout_missed(unsigned long ptr) { unsigned long flags; struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)ptr; struct ScsiReqBlk *srb; dprintkl(KERN_DEBUG, "Chip forgot to produce SelTO IRQ!\n"); if (!acb->active_dcb || !acb->active_dcb->active_srb) { dprintkl(KERN_DEBUG, "... but no cmd pending? Oops!\n"); return; } DC395x_LOCK_IO(acb->scsi_host, flags); srb = acb->active_dcb->active_srb; disconnect(acb); DC395x_UNLOCK_IO(acb->scsi_host, flags); } #endif static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, struct ScsiReqBlk* srb) { … } #define DC395x_ENABLE_MSGOUT … /* abort command */ static inline void enable_msgout_abort(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { … } /** * dc395x_handle_interrupt - Handle an interrupt that has been confirmed to * have been triggered for this card. * * @acb: a pointer to the adpter control block * @scsi_status: the status return when we checked the card **/ static void dc395x_handle_interrupt(struct AdapterCtlBlk *acb, u16 scsi_status) { … } static irqreturn_t dc395x_interrupt(int irq, void *dev_id) { … } static void msgout_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { … } static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { … } static void command_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { … } static void command_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { … } /* * Verify that the remaining space in the hw sg lists is the same as * the count of remaining bytes in srb->total_xfer_length */ static void sg_verify_length(struct ScsiReqBlk *srb) { … } /* * Compute the next Scatter Gather list index and adjust its length * and address if necessary */ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) { … } /* * We have transferred a single byte (PIO mode?) and need to update * the count of bytes remaining (total_xfer_length) and update the sg * entry to either point to next byte in the current sg entry, or of * already at the end to point to the start of the next sg entry */ static void sg_subtract_one(struct ScsiReqBlk *srb) { … } /* * cleanup_after_transfer * * Makes sure, DMA and SCSI engine are empty, after the transfer has finished * KG: Currently called from StatusPhase1 () * Should probably also be called from other places * Best might be to call it in DataXXPhase0, if new phase will differ */ static void cleanup_after_transfer(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { … } /* * Those no of bytes will be transferred w/ PIO through the SCSI FIFO * Seems to be needed for unknown reasons; could be a hardware bug :-( */ #define DC395x_LASTPIO … static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { … } static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { … } static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { … } static void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { … } static void data_io_transfer(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 io_dir) { … } static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { … } static void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { … } /* Check if the message is complete */ static inline u8 msgin_completed(u8 * msgbuf, u32 len) { … } /* reject_msg */ static inline void msgin_reject(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { … } static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, u8 tag) { … } static inline void reprogram_regs(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) { … } /* set async transfer mode */ static void msgin_set_async(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { … } /* set sync transfer mode */ static void msgin_set_sync(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { … } static inline void msgin_set_nowide(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { … } static void msgin_set_wide(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { … } /* * extended message codes: * * code description * * 02h Reserved * 00h MODIFY DATA POINTER * 01h SYNCHRONOUS DATA TRANSFER REQUEST * 03h WIDE DATA TRANSFER REQUEST * 04h - 7Fh Reserved * 80h - FFh Vendor specific */ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { … } static void msgin_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { … } static void nop0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { … } static void nop1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { … } static void set_xfer_rate(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) { … } static void disconnect(struct AdapterCtlBlk *acb) { … } static void reselect(struct AdapterCtlBlk *acb) { … } static inline u8 tagq_blacklist(char *name) { … } static void disc_tagq_set(struct DeviceCtlBlk *dcb, struct ScsiInqData *ptr) { … } static void add_dev(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, struct ScsiInqData *ptr) { … } /* unmap mapped pci regions from SRB */ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { … } /* unmap mapped pci sense buffer from SRB */ static void pci_unmap_srb_sense(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { … } /* * Complete execution of a SCSI command * Signal completion to the generic SCSI driver */ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { … } /* abort all cmds in our queues */ static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, struct scsi_cmnd *cmd, u8 force) { … } static void reset_scsi_bus(struct AdapterCtlBlk *acb) { … } static void set_basic_config(struct AdapterCtlBlk *acb) { … } static void scsi_reset_detect(struct AdapterCtlBlk *acb) { … } static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { … } /** * device_alloc - Allocate a new device instance. This create the * devices instance and sets up all the data items. The adapter * instance is required to obtain confiuration information for this * device. This does *not* add this device to the adapters device * list. * * @acb: The adapter to obtain configuration information from. * @target: The target for the new device. * @lun: The lun for the new device. * * Return the new device if successful or NULL on failure. **/ static struct DeviceCtlBlk *device_alloc(struct AdapterCtlBlk *acb, u8 target, u8 lun) { … } /** * adapter_add_device - Adds the device instance to the adaptor instance. * * @acb: The adapter device to be updated * @dcb: A newly created and initialised device instance to add. **/ static void adapter_add_device(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) { … } /** * adapter_remove_device - Removes the device instance from the adaptor * instance. The device instance is not check in any way or freed by this. * The caller is expected to take care of that. This will simply remove the * device from the adapters data strcutures. * * @acb: The adapter device to be updated * @dcb: A device that has previously been added to the adapter. **/ static void adapter_remove_device(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) { … } /** * adapter_remove_and_free_device - Removes a single device from the adapter * and then frees the device information. * * @acb: The adapter device to be updated * @dcb: A device that has previously been added to the adapter. */ static void adapter_remove_and_free_device(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) { … } /** * adapter_remove_and_free_all_devices - Removes and frees all of the * devices associated with the specified adapter. * * @acb: The adapter from which all devices should be removed. **/ static void adapter_remove_and_free_all_devices(struct AdapterCtlBlk* acb) { … } /** * dc395x_slave_alloc - Called by the scsi mid layer to tell us about a new * scsi device that we need to deal with. We allocate a new device and then * insert that device into the adapters device list. * * @scsi_device: The new scsi device that we need to handle. **/ static int dc395x_slave_alloc(struct scsi_device *scsi_device) { … } /** * dc395x_slave_destroy - Called by the scsi mid layer to tell us about a * device that is going away. * * @scsi_device: The new scsi device that we need to handle. **/ static void dc395x_slave_destroy(struct scsi_device *scsi_device) { … } /** * trms1040_wait_30us: wait for 30 us * * Waits for 30us (using the chip by the looks of it..) * * @io_port: base I/O address **/ static void trms1040_wait_30us(unsigned long io_port) { … } /** * trms1040_write_cmd - write the secified command and address to * chip * * @io_port: base I/O address * @cmd: SB + op code (command) to send * @addr: address to send **/ static void trms1040_write_cmd(unsigned long io_port, u8 cmd, u8 addr) { … } /** * trms1040_set_data - store a single byte in the eeprom * * Called from write all to write a single byte into the SSEEPROM * Which is done one bit at a time. * * @io_port: base I/O address * @addr: offset into EEPROM * @byte: bytes to write **/ static void trms1040_set_data(unsigned long io_port, u8 addr, u8 byte) { … } /** * trms1040_write_all - write 128 bytes to the eeprom * * Write the supplied 128 bytes to the chips SEEPROM * * @eeprom: the data to write * @io_port: the base io port **/ static void trms1040_write_all(struct NvRamType *eeprom, unsigned long io_port) { … } /** * trms1040_get_data - get a single byte from the eeprom * * Called from read all to read a single byte into the SSEEPROM * Which is done one bit at a time. * * @io_port: base I/O address * @addr: offset into SEEPROM * * Returns the byte read. **/ static u8 trms1040_get_data(unsigned long io_port, u8 addr) { … } /** * trms1040_read_all - read all bytes from the eeprom * * Read the 128 bytes from the SEEPROM. * * @eeprom: where to store the data * @io_port: the base io port **/ static void trms1040_read_all(struct NvRamType *eeprom, unsigned long io_port) { … } /** * check_eeprom - get and check contents of the eeprom * * Read seeprom 128 bytes into the memory provider in eeprom. * Checks the checksum and if it's not correct it uses a set of default * values. * * @eeprom: caller allocated strcuture to read the eeprom data into * @io_port: io port to read from **/ static void check_eeprom(struct NvRamType *eeprom, unsigned long io_port) { … } /** * print_eeprom_settings - output the eeprom settings * to the kernel log so people can see what they were. * * @eeprom: The eeprom data strucutre to show details for. **/ static void print_eeprom_settings(struct NvRamType *eeprom) { … } /* Free SG tables */ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb) { … } /* * Allocate SG tables; as we have to pci_map them, an SG list (struct SGentry*) * should never cross a page boundary */ static int adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) { … } /** * adapter_print_config - print adapter connection and termination * config * * The io port in the adapter needs to have been set before calling * this function. * * @acb: The adapter to print the information for. **/ static void adapter_print_config(struct AdapterCtlBlk *acb) { … } /** * adapter_init_params - Initialize the various parameters in the * adapter structure. Note that the pointer to the scsi_host is set * early (when this instance is created) and the io_port and irq * values are set later after they have been reserved. This just gets * everything set to a good starting position. * * The eeprom structure in the adapter needs to have been set before * calling this function. * * @acb: The adapter to initialize. **/ static void adapter_init_params(struct AdapterCtlBlk *acb) { … } /** * adapter_init_scsi_host - Initialize the scsi host instance based on * values that we have already stored in the adapter instance. There's * some mention that a lot of these are deprecated, so we won't use * them (we'll use the ones in the adapter instance) but we'll fill * them in in case something else needs them. * * The eeprom structure, irq and io ports in the adapter need to have * been set before calling this function. * * @host: The scsi host instance to fill in the values for. **/ static void adapter_init_scsi_host(struct Scsi_Host *host) { … } /** * adapter_init_chip - Get the chip into a know state and figure out * some of the settings that apply to this adapter. * * The io port in the adapter needs to have been set before calling * this function. The config will be configured correctly on return. * * @acb: The adapter which we are to init. **/ static void adapter_init_chip(struct AdapterCtlBlk *acb) { … } /** * adapter_init - Grab the resource for the card, setup the adapter * information, set the card into a known state, create the various * tables etc etc. This basically gets all adapter information all up * to date, initialised and gets the chip in sync with it. * * @acb: The adapter which we are to init. * @io_port: The base I/O port * @io_port_len: The I/O port size * @irq: IRQ * * Returns 0 if the initialization succeeds, any other value on * failure. **/ static int adapter_init(struct AdapterCtlBlk *acb, unsigned long io_port, u32 io_port_len, unsigned int irq) { … } /** * adapter_uninit_chip - cleanly shut down the scsi controller chip, * stopping all operations and disabling interrupt generation on the * card. * * @acb: The adapter which we are to shutdown. **/ static void adapter_uninit_chip(struct AdapterCtlBlk *acb) { … } /** * adapter_uninit - Shut down the chip and release any resources that * we had allocated. Once this returns the adapter should not be used * anymore. * * @acb: The adapter which we are to un-initialize. **/ static void adapter_uninit(struct AdapterCtlBlk *acb) { … } #undef YESNO #define YESNO(YN) … static int dc395x_show_info(struct seq_file *m, struct Scsi_Host *host) { … } static const struct scsi_host_template dc395x_driver_template = …; /** * banner_display - Display banner on first instance of driver * initialized. **/ static void banner_display(void) { … } /** * dc395x_init_one - Initialise a single instance of the adapter. * * The PCI layer will call this once for each instance of the adapter * that it finds in the system. The pci_dev strcuture indicates which * instance we are being called from. * * @dev: The PCI device to initialize. * @id: Looks like a pointer to the entry in our pci device table * that was actually matched by the PCI subsystem. * * Returns 0 on success, or an error code (-ve) on failure. **/ static int dc395x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { … } /** * dc395x_remove_one - Called to remove a single instance of the * adapter. * * @dev: The PCI device to initialize. **/ static void dc395x_remove_one(struct pci_dev *dev) { … } static struct pci_device_id dc395x_pci_table[] = …; MODULE_DEVICE_TABLE(pci, dc395x_pci_table); static struct pci_driver dc395x_driver = …; module_pci_driver(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …;