Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* |
| 2 | * |
| 3 | * Linux MegaRAID device driver |
| 4 | * |
| 5 | * Copyright (c) 2003-2004 LSI Logic Corporation. |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or |
| 8 | * modify it under the terms of the GNU General Public License |
| 9 | * as published by the Free Software Foundation; either version |
| 10 | * 2 of the License, or (at your option) any later version. |
| 11 | * |
| 12 | * FILE : mega_common.h |
| 13 | * |
| 14 | * Libaray of common routine used by all low-level megaraid drivers |
| 15 | */ |
| 16 | |
| 17 | #ifndef _MEGA_COMMON_H_ |
| 18 | #define _MEGA_COMMON_H_ |
| 19 | |
| 20 | #include <linux/kernel.h> |
| 21 | #include <linux/types.h> |
| 22 | #include <linux/pci.h> |
| 23 | #include <linux/spinlock.h> |
Matthias Kaehlcke | 0c2cc43 | 2007-07-09 12:00:11 -0700 | [diff] [blame] | 24 | #include <linux/mutex.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 25 | #include <linux/interrupt.h> |
| 26 | #include <linux/delay.h> |
| 27 | #include <linux/blkdev.h> |
| 28 | #include <linux/list.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 29 | #include <linux/moduleparam.h> |
Ju, Seokmann | 672b2d3 | 2005-05-16 18:32:17 -0400 | [diff] [blame] | 30 | #include <linux/dma-mapping.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 31 | #include <asm/semaphore.h> |
| 32 | #include <scsi/scsi.h> |
| 33 | #include <scsi/scsi_cmnd.h> |
| 34 | #include <scsi/scsi_device.h> |
| 35 | #include <scsi/scsi_host.h> |
| 36 | |
| 37 | |
| 38 | #define LSI_MAX_CHANNELS 16 |
| 39 | #define LSI_MAX_LOGICAL_DRIVES_64LD (64+1) |
| 40 | |
Ju, Seokmann | fbf6080 | 2006-07-25 08:44:48 -0600 | [diff] [blame] | 41 | #define HBA_SIGNATURE_64_BIT 0x299 |
| 42 | #define PCI_CONF_AMISIG64 0xa4 |
| 43 | |
Ju, Seokmann | aa677bc | 2006-07-25 08:44:58 -0600 | [diff] [blame] | 44 | #define MEGA_SCSI_INQ_EVPD 1 |
| 45 | #define MEGA_INVALID_FIELD_IN_CDB 0x24 |
| 46 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 47 | |
| 48 | /** |
| 49 | * scb_t - scsi command control block |
Randy Dunlap | a69b74d | 2007-01-05 22:41:48 -0800 | [diff] [blame] | 50 | * @ccb : command control block for individual driver |
| 51 | * @list : list of control blocks |
| 52 | * @gp : general purpose field for LLDs |
| 53 | * @sno : all SCBs have a serial number |
| 54 | * @scp : associated scsi command |
| 55 | * @state : current state of scb |
| 56 | * @dma_dir : direction of data transfer |
| 57 | * @dma_type : transfer with sg list, buffer, or no data transfer |
| 58 | * @dev_channel : actual channel on the device |
| 59 | * @dev_target : actual target on the device |
| 60 | * @status : completion status |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 61 | * |
| 62 | * This is our central data structure to issue commands the each driver. |
| 63 | * Driver specific data structures are maintained in the ccb field. |
| 64 | * scb provides a field 'gp', which can be used by LLD for its own purposes |
| 65 | * |
| 66 | * dev_channel and dev_target must be initialized with the actual channel and |
| 67 | * target on the controller. |
| 68 | */ |
| 69 | typedef struct { |
| 70 | caddr_t ccb; |
| 71 | struct list_head list; |
| 72 | unsigned long gp; |
| 73 | unsigned int sno; |
| 74 | struct scsi_cmnd *scp; |
| 75 | uint32_t state; |
| 76 | uint32_t dma_direction; |
| 77 | uint32_t dma_type; |
| 78 | uint16_t dev_channel; |
| 79 | uint16_t dev_target; |
| 80 | uint32_t status; |
| 81 | } scb_t; |
| 82 | |
| 83 | /* |
| 84 | * SCB states as it transitions from one state to another |
| 85 | */ |
| 86 | #define SCB_FREE 0x0000 /* on the free list */ |
| 87 | #define SCB_ACTIVE 0x0001 /* off the free list */ |
| 88 | #define SCB_PENDQ 0x0002 /* on the pending queue */ |
| 89 | #define SCB_ISSUED 0x0004 /* issued - owner f/w */ |
| 90 | #define SCB_ABORT 0x0008 /* Got an abort for this one */ |
| 91 | #define SCB_RESET 0x0010 /* Got a reset for this one */ |
| 92 | |
| 93 | /* |
| 94 | * DMA types for scb |
| 95 | */ |
| 96 | #define MRAID_DMA_NONE 0x0000 /* no data transfer for this command */ |
| 97 | #define MRAID_DMA_WSG 0x0001 /* data transfer using a sg list */ |
| 98 | #define MRAID_DMA_WBUF 0x0002 /* data transfer using a contiguous buffer */ |
| 99 | |
| 100 | |
| 101 | /** |
| 102 | * struct adapter_t - driver's initialization structure |
Randy Dunlap | a69b74d | 2007-01-05 22:41:48 -0800 | [diff] [blame] | 103 | * @aram dpc_h : tasklet handle |
| 104 | * @pdev : pci configuration pointer for kernel |
| 105 | * @host : pointer to host structure of mid-layer |
| 106 | * @lock : synchronization lock for mid-layer and driver |
| 107 | * @quiescent : driver is quiescent for now. |
| 108 | * @outstanding_cmds : number of commands pending in the driver |
| 109 | * @kscb_list : pointer to the bulk of SCBs pointers for IO |
| 110 | * @kscb_pool : pool of free scbs for IO |
| 111 | * @kscb_pool_lock : lock for pool of free scbs |
| 112 | * @pend_list : pending commands list |
| 113 | * @pend_list_lock : exclusion lock for pending commands list |
| 114 | * @completed_list : list of completed commands |
| 115 | * @completed_list_lock : exclusion lock for list of completed commands |
| 116 | * @sglen : max sg elements supported |
| 117 | * @device_ids : to convert kernel device addr to our devices. |
| 118 | * @raid_device : raid adapter specific pointer |
| 119 | * @max_channel : maximum channel number supported - inclusive |
| 120 | * @max_target : max target supported - inclusive |
| 121 | * @max_lun : max lun supported - inclusive |
| 122 | * @unique_id : unique identifier for each adapter |
| 123 | * @irq : IRQ for this adapter |
| 124 | * @ito : internal timeout value, (-1) means no timeout |
| 125 | * @ibuf : buffer to issue internal commands |
| 126 | * @ibuf_dma_h : dma handle for the above buffer |
| 127 | * @uscb_list : SCB pointers for user cmds, common mgmt module |
| 128 | * @uscb_pool : pool of SCBs for user commands |
| 129 | * @uscb_pool_lock : exclusion lock for these SCBs |
| 130 | * @max_cmds : max outstanding commands |
| 131 | * @fw_version : firmware version |
| 132 | * @bios_version : bios version |
| 133 | * @max_cdb_sz : biggest CDB size supported. |
| 134 | * @ha : is high availability present - clustering |
| 135 | * @init_id : initiator ID, the default value should be 7 |
| 136 | * @max_sectors : max sectors per request |
| 137 | * @cmd_per_lun : max outstanding commands per LUN |
| 138 | * @being_detached : set when unloading, no more mgmt calls |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 139 | * |
| 140 | * |
| 141 | * mraid_setup_device_map() can be called anytime after the device map is |
| 142 | * available and MRAID_GET_DEVICE_MAP() can be called whenever the mapping is |
| 143 | * required, usually from LLD's queue entry point. The formar API sets up the |
| 144 | * MRAID_IS_LOGICAL(adapter_t *, struct scsi_cmnd *) to find out if the |
| 145 | * device in question is a logical drive. |
| 146 | * |
| 147 | * quiescent flag should be set by the driver if it is not accepting more |
| 148 | * commands |
| 149 | * |
| 150 | * NOTE: The fields of this structures are placed to minimize cache misses |
| 151 | */ |
| 152 | |
| 153 | // amount of space required to store the bios and firmware version strings |
| 154 | #define VERSION_SIZE 16 |
| 155 | |
| 156 | typedef struct { |
| 157 | struct tasklet_struct dpc_h; |
| 158 | struct pci_dev *pdev; |
| 159 | struct Scsi_Host *host; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 160 | spinlock_t lock; |
| 161 | uint8_t quiescent; |
| 162 | int outstanding_cmds; |
| 163 | scb_t *kscb_list; |
| 164 | struct list_head kscb_pool; |
| 165 | spinlock_t kscb_pool_lock; |
| 166 | struct list_head pend_list; |
| 167 | spinlock_t pend_list_lock; |
| 168 | struct list_head completed_list; |
| 169 | spinlock_t completed_list_lock; |
| 170 | uint16_t sglen; |
| 171 | int device_ids[LSI_MAX_CHANNELS] |
| 172 | [LSI_MAX_LOGICAL_DRIVES_64LD]; |
| 173 | caddr_t raid_device; |
| 174 | uint8_t max_channel; |
| 175 | uint16_t max_target; |
| 176 | uint8_t max_lun; |
| 177 | |
| 178 | uint32_t unique_id; |
Eric W. Biederman | f5ebbeb | 2006-09-25 16:59:01 -0700 | [diff] [blame] | 179 | int irq; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 180 | uint8_t ito; |
| 181 | caddr_t ibuf; |
| 182 | dma_addr_t ibuf_dma_h; |
| 183 | scb_t *uscb_list; |
| 184 | struct list_head uscb_pool; |
| 185 | spinlock_t uscb_pool_lock; |
| 186 | int max_cmds; |
| 187 | uint8_t fw_version[VERSION_SIZE]; |
| 188 | uint8_t bios_version[VERSION_SIZE]; |
| 189 | uint8_t max_cdb_sz; |
| 190 | uint8_t ha; |
| 191 | uint16_t init_id; |
| 192 | uint16_t max_sectors; |
| 193 | uint16_t cmd_per_lun; |
| 194 | atomic_t being_detached; |
| 195 | } adapter_t; |
| 196 | |
| 197 | #define SCSI_FREE_LIST_LOCK(adapter) (&adapter->kscb_pool_lock) |
| 198 | #define USER_FREE_LIST_LOCK(adapter) (&adapter->uscb_pool_lock) |
| 199 | #define PENDING_LIST_LOCK(adapter) (&adapter->pend_list_lock) |
| 200 | #define COMPLETED_LIST_LOCK(adapter) (&adapter->completed_list_lock) |
| 201 | |
| 202 | |
| 203 | // conversion from scsi command |
| 204 | #define SCP2HOST(scp) (scp)->device->host // to host |
| 205 | #define SCP2HOSTDATA(scp) SCP2HOST(scp)->hostdata // to soft state |
| 206 | #define SCP2CHANNEL(scp) (scp)->device->channel // to channel |
| 207 | #define SCP2TARGET(scp) (scp)->device->id // to target |
| 208 | #define SCP2LUN(scp) (scp)->device->lun // to LUN |
| 209 | |
| 210 | // generic macro to convert scsi command and host to controller's soft state |
| 211 | #define SCSIHOST2ADAP(host) (((caddr_t *)(host->hostdata))[0]) |
| 212 | #define SCP2ADAPTER(scp) (adapter_t *)SCSIHOST2ADAP(SCP2HOST(scp)) |
| 213 | |
| 214 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 215 | #define MRAID_IS_LOGICAL(adp, scp) \ |
| 216 | (SCP2CHANNEL(scp) == (adp)->max_channel) ? 1 : 0 |
| 217 | |
| 218 | #define MRAID_IS_LOGICAL_SDEV(adp, sdev) \ |
| 219 | (sdev->channel == (adp)->max_channel) ? 1 : 0 |
| 220 | |
Randy Dunlap | a69b74d | 2007-01-05 22:41:48 -0800 | [diff] [blame] | 221 | /** |
| 222 | * MRAID_GET_DEVICE_MAP - device ids |
| 223 | * @adp : adapter's soft state |
| 224 | * @scp : mid-layer scsi command pointer |
| 225 | * @p_chan : physical channel on the controller |
| 226 | * @target : target id of the device or logical drive number |
| 227 | * @islogical : set if the command is for the logical drive |
| 228 | * |
| 229 | * Macro to retrieve information about device class, logical or physical and |
| 230 | * the corresponding physical channel and target or logical drive number |
| 231 | */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 232 | #define MRAID_GET_DEVICE_MAP(adp, scp, p_chan, target, islogical) \ |
| 233 | /* \ |
| 234 | * Is the request coming for the virtual channel \ |
| 235 | */ \ |
| 236 | islogical = MRAID_IS_LOGICAL(adp, scp); \ |
| 237 | \ |
| 238 | /* \ |
| 239 | * Get an index into our table of drive ids mapping \ |
| 240 | */ \ |
| 241 | if (islogical) { \ |
| 242 | p_chan = 0xFF; \ |
| 243 | target = \ |
| 244 | (adp)->device_ids[(adp)->max_channel][SCP2TARGET(scp)]; \ |
| 245 | } \ |
| 246 | else { \ |
| 247 | p_chan = ((adp)->device_ids[SCP2CHANNEL(scp)] \ |
| 248 | [SCP2TARGET(scp)] >> 8) & 0xFF; \ |
| 249 | target = ((adp)->device_ids[SCP2CHANNEL(scp)] \ |
| 250 | [SCP2TARGET(scp)] & 0xFF); \ |
| 251 | } |
| 252 | |
| 253 | /* |
| 254 | * ### Helper routines ### |
| 255 | */ |
| 256 | #define LSI_DBGLVL mraid_debug_level // each LLD must define a global |
| 257 | // mraid_debug_level |
| 258 | |
| 259 | #ifdef DEBUG |
| 260 | #if defined (_ASSERT_PANIC) |
| 261 | #define ASSERT_ACTION panic |
| 262 | #else |
| 263 | #define ASSERT_ACTION printk |
| 264 | #endif |
| 265 | |
| 266 | #define ASSERT(expression) \ |
| 267 | if (!(expression)) { \ |
| 268 | ASSERT_ACTION("assertion failed:(%s), file: %s, line: %d:%s\n", \ |
| 269 | #expression, __FILE__, __LINE__, __FUNCTION__); \ |
| 270 | } |
| 271 | #else |
| 272 | #define ASSERT(expression) |
| 273 | #endif |
| 274 | |
Randy Dunlap | 59f19a9 | 2007-01-09 21:40:52 -0800 | [diff] [blame] | 275 | /** |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 276 | * struct mraid_pci_blk - structure holds DMA memory block info |
Randy Dunlap | a69b74d | 2007-01-05 22:41:48 -0800 | [diff] [blame] | 277 | * @vaddr : virtual address to a memory block |
| 278 | * @dma_addr : DMA handle to a memory block |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 279 | * |
| 280 | * This structure is filled up for the caller. It is the responsibilty of the |
| 281 | * caller to allocate this array big enough to store addresses for all |
| 282 | * requested elements |
| 283 | */ |
| 284 | struct mraid_pci_blk { |
| 285 | caddr_t vaddr; |
| 286 | dma_addr_t dma_addr; |
| 287 | }; |
| 288 | |
| 289 | #endif // _MEGA_COMMON_H_ |
| 290 | |
| 291 | // vim: set ts=8 sw=8 tw=78: |