| Commit | Line | Data |
|---|---|---|
| 984263bc MD |
1 | /*- |
| 2 | * Copyright (c) 1999,2000 Michael Smith | |
| 3 | * Copyright (c) 2000 BSDi | |
| 4 | * All rights reserved. | |
| 5 | * | |
| 6 | * Redistribution and use in source and binary forms, with or without | |
| 7 | * modification, are permitted provided that the following conditions | |
| 8 | * are met: | |
| 9 | * 1. Redistributions of source code must retain the above copyright | |
| 10 | * notice, this list of conditions and the following disclaimer. | |
| 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 12 | * notice, this list of conditions and the following disclaimer in the | |
| 13 | * documentation and/or other materials provided with the distribution. | |
| 14 | * | |
| 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
| 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
| 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 25 | * SUCH DAMAGE. | |
| 26 | * | |
| 27 | * Copyright (c) 2002 Eric Moore | |
| 28 | * Copyright (c) 2002 LSI Logic Corporation | |
| 29 | * All rights reserved. | |
| 30 | * | |
| 31 | * Redistribution and use in source and binary forms, with or without | |
| 32 | * modification, are permitted provided that the following conditions | |
| 33 | * are met: | |
| 34 | * 1. Redistributions of source code must retain the above copyright | |
| 35 | * notice, this list of conditions and the following disclaimer. | |
| 36 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 37 | * notice, this list of conditions and the following disclaimer in the | |
| 38 | * documentation and/or other materials provided with the distribution. | |
| 39 | * 3. The party using or redistributing the source code and binary forms | |
| 40 | * agrees to the disclaimer below and the terms and conditions set forth | |
| 41 | * herein. | |
| 42 | * | |
| 43 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
| 44 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 45 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 46 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
| 47 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 48 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 49 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 50 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 51 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 52 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 53 | * SUCH DAMAGE. | |
| 54 | * | |
| 1fcd0ba2 | 55 | * |
| 71fdcb31 | 56 | * $FreeBSD: src/sys/dev/amr/amrvar.h,v 1.39 2012/08/31 09:42:46 scottl Exp $ |
| 984263bc MD |
57 | */ |
| 58 | ||
| 1fcd0ba2 SW |
59 | #include <sys/buf2.h> |
| 60 | #include <sys/devicestat.h> | |
| 61 | #include <sys/disk.h> | |
| 62 | #include <sys/lock.h> | |
| 63 | #include <sys/sysctl.h> | |
| 7f2216bc | 64 | |
| 1fcd0ba2 | 65 | #define LSI_DESC_PCI "LSILogic MegaRAID 1.53" |
| 984263bc MD |
66 | |
| 67 | #ifdef AMR_DEBUG | |
| e3869ec7 SW |
68 | # define debug(level, fmt, args...) do {if (level <= AMR_DEBUG) kprintf("%s: " fmt "\n", __func__ , ##args);} while(0) |
| 69 | # define debug_called(level) do {if (level <= AMR_DEBUG) kprintf("%s: called\n", __func__);} while(0) | |
| 984263bc | 70 | #else |
| 1fcd0ba2 SW |
71 | # define debug(level, fmt, args...) do {} while (0) |
| 72 | # define debug_called(level) do {} while (0) | |
| 984263bc | 73 | #endif |
| 1fcd0ba2 | 74 | #define xdebug(fmt, args...) printf("%s: " fmt "\n", __func__ , ##args) |
| 984263bc MD |
75 | |
| 76 | /* | |
| 77 | * Per-logical-drive datastructure | |
| 78 | */ | |
| 79 | struct amr_logdrive | |
| 80 | { | |
| 81 | u_int32_t al_size; | |
| 82 | int al_state; | |
| 83 | int al_properties; | |
| 84 | ||
| 85 | /* synthetic geometry */ | |
| 86 | int al_cylinders; | |
| 87 | int al_heads; | |
| 88 | int al_sectors; | |
| 89 | ||
| 90 | /* driver */ | |
| 91 | device_t al_disk; | |
| 92 | }; | |
| 93 | ||
| 94 | /* | |
| 95 | * Due to the difficulty of using the zone allocator to create a new | |
| 96 | * zone from within a module, we use our own clustering to reduce | |
| 97 | * memory wastage due to allocating lots of these small structures. | |
| 98 | * | |
| 99 | * 16k gives us a little under 200 command structures, which should | |
| 100 | * normally be plenty. We will grab more if we need them. | |
| 101 | */ | |
| 102 | ||
| 103 | #define AMR_CMD_CLUSTERSIZE (16 * 1024) | |
| 104 | ||
| 1fcd0ba2 SW |
105 | typedef STAILQ_HEAD(, amr_command) ac_qhead_t; |
| 106 | typedef STAILQ_ENTRY(amr_command) ac_link_t; | |
| 107 | ||
| 108 | union amr_ccb { | |
| 109 | struct amr_passthrough ccb_pthru; | |
| 110 | struct amr_ext_passthrough ccb_epthru; | |
| 111 | uint8_t bytes[128]; | |
| 112 | }; | |
| 113 | ||
| 984263bc MD |
114 | /* |
| 115 | * Per-command control structure. | |
| 116 | */ | |
| 117 | struct amr_command | |
| 118 | { | |
| 1fcd0ba2 | 119 | ac_link_t ac_link; |
| 984263bc MD |
120 | |
| 121 | struct amr_softc *ac_sc; | |
| 122 | u_int8_t ac_slot; | |
| 123 | int ac_status; /* command completion status */ | |
| 1fcd0ba2 SW |
124 | union { |
| 125 | struct amr_sgentry *sg32; | |
| 126 | struct amr_sg64entry *sg64; | |
| 127 | } ac_sg; | |
| 128 | u_int32_t ac_sgbusaddr; | |
| 129 | u_int32_t ac_sg64_lo; | |
| 130 | u_int32_t ac_sg64_hi; | |
| 984263bc MD |
131 | struct amr_mailbox ac_mailbox; |
| 132 | int ac_flags; | |
| 133 | #define AMR_CMD_DATAIN (1<<0) | |
| 134 | #define AMR_CMD_DATAOUT (1<<1) | |
| 1fcd0ba2 | 135 | #define AMR_CMD_CCB (1<<2) |
| 984263bc MD |
136 | #define AMR_CMD_PRIORITY (1<<4) |
| 137 | #define AMR_CMD_MAPPED (1<<5) | |
| 138 | #define AMR_CMD_SLEEP (1<<6) | |
| 139 | #define AMR_CMD_BUSY (1<<7) | |
| 1fcd0ba2 SW |
140 | #define AMR_CMD_SG64 (1<<8) |
| 141 | #define AC_IS_SG64(ac) ((ac)->ac_flags & AMR_CMD_SG64) | |
| 142 | u_int ac_retries; | |
| 984263bc MD |
143 | |
| 144 | struct bio *ac_bio; | |
| 1fcd0ba2 SW |
145 | void (* ac_complete)(struct amr_command *ac); |
| 146 | void *ac_private; | |
| 984263bc MD |
147 | |
| 148 | void *ac_data; | |
| 149 | size_t ac_length; | |
| 150 | bus_dmamap_t ac_dmamap; | |
| 1fcd0ba2 | 151 | bus_dmamap_t ac_dma64map; |
| 984263bc | 152 | |
| 1fcd0ba2 SW |
153 | bus_dma_tag_t ac_tag; |
| 154 | bus_dmamap_t ac_datamap; | |
| 155 | int ac_nsegments; | |
| 156 | uint32_t ac_mb_physaddr; | |
| 984263bc | 157 | |
| 1fcd0ba2 SW |
158 | union amr_ccb *ac_ccb; |
| 159 | uint32_t ac_ccb_busaddr; | |
| 984263bc MD |
160 | }; |
| 161 | ||
| 162 | struct amr_command_cluster | |
| 163 | { | |
| 164 | TAILQ_ENTRY(amr_command_cluster) acc_link; | |
| 165 | struct amr_command acc_command[0]; | |
| 166 | }; | |
| 167 | ||
| 168 | #define AMR_CMD_CLUSTERCOUNT ((AMR_CMD_CLUSTERSIZE - sizeof(struct amr_command_cluster)) / \ | |
| 169 | sizeof(struct amr_command)) | |
| 170 | ||
| 171 | /* | |
| 172 | * Per-controller-instance data | |
| 173 | */ | |
| 174 | struct amr_softc | |
| 175 | { | |
| 176 | /* bus attachments */ | |
| 177 | device_t amr_dev; | |
| 178 | struct resource *amr_reg; /* control registers */ | |
| 179 | bus_space_handle_t amr_bhandle; | |
| 180 | bus_space_tag_t amr_btag; | |
| 181 | bus_dma_tag_t amr_parent_dmat; /* parent DMA tag */ | |
| 182 | bus_dma_tag_t amr_buffer_dmat; /* data buffer DMA tag */ | |
| 1fcd0ba2 | 183 | bus_dma_tag_t amr_buffer64_dmat; |
| 984263bc MD |
184 | struct resource *amr_irq; /* interrupt */ |
| 185 | void *amr_intr; | |
| 186 | ||
| 187 | /* mailbox */ | |
| 188 | volatile struct amr_mailbox *amr_mailbox; | |
| 189 | volatile struct amr_mailbox64 *amr_mailbox64; | |
| 190 | u_int32_t amr_mailboxphys; | |
| 191 | bus_dma_tag_t amr_mailbox_dmat; | |
| 192 | bus_dmamap_t amr_mailbox_dmamap; | |
| 193 | ||
| 194 | /* scatter/gather lists and their controller-visible mappings */ | |
| 195 | struct amr_sgentry *amr_sgtable; /* s/g lists */ | |
| 1fcd0ba2 | 196 | struct amr_sg64entry *amr_sg64table; /* 64bit s/g lists */ |
| 984263bc MD |
197 | u_int32_t amr_sgbusaddr; /* s/g table base address in bus space */ |
| 198 | bus_dma_tag_t amr_sg_dmat; /* s/g buffer DMA tag */ | |
| 199 | bus_dmamap_t amr_sg_dmamap; /* map for s/g buffers */ | |
| 200 | ||
| 1fcd0ba2 SW |
201 | union amr_ccb *amr_ccb; |
| 202 | uint32_t amr_ccb_busaddr; | |
| 203 | bus_dma_tag_t amr_ccb_dmat; | |
| 204 | bus_dmamap_t amr_ccb_dmamap; | |
| 205 | ||
| 984263bc | 206 | /* controller limits and features */ |
| 1fcd0ba2 | 207 | int amr_nextslot; /* Next slot to use for newly allocated commands */ |
| 984263bc MD |
208 | int amr_maxio; /* maximum number of I/O transactions */ |
| 209 | int amr_maxdrives; /* max number of logical drives */ | |
| 210 | int amr_maxchan; /* count of SCSI channels */ | |
| 211 | ||
| 212 | /* connected logical drives */ | |
| 213 | struct amr_logdrive amr_drive[AMR_MAXLD]; | |
| 214 | ||
| 215 | /* controller state */ | |
| 216 | int amr_state; | |
| 217 | #define AMR_STATE_OPEN (1<<0) | |
| 218 | #define AMR_STATE_SUSPEND (1<<1) | |
| 219 | #define AMR_STATE_INTEN (1<<2) | |
| 220 | #define AMR_STATE_SHUTDOWN (1<<3) | |
| 1fcd0ba2 SW |
221 | #define AMR_STATE_CRASHDUMP (1<<4) |
| 222 | #define AMR_STATE_QUEUE_FRZN (1<<5) | |
| 223 | #define AMR_STATE_LD_DELETE (1<<6) | |
| 224 | #define AMR_STATE_REMAP_LD (1<<7) | |
| 984263bc MD |
225 | |
| 226 | /* per-controller queues */ | |
| 227 | struct bio_queue_head amr_bioq; /* pending I/O with no commands */ | |
| 1fcd0ba2 | 228 | ac_qhead_t amr_ready; /* commands ready to be submitted */ |
| 984263bc MD |
229 | struct amr_command *amr_busycmd[AMR_MAXCMD]; |
| 230 | int amr_busyslots; | |
| 1fcd0ba2 | 231 | ac_qhead_t amr_freecmds; |
| 984263bc MD |
232 | TAILQ_HEAD(,amr_command_cluster) amr_cmd_clusters; |
| 233 | ||
| 234 | /* CAM attachments for passthrough */ | |
| 235 | struct cam_sim *amr_cam_sim[AMR_MAX_CHANNELS]; | |
| 236 | TAILQ_HEAD(, ccb_hdr) amr_cam_ccbq; | |
| 1fcd0ba2 | 237 | struct cam_devq *amr_cam_devq; |
| 984263bc MD |
238 | |
| 239 | /* control device */ | |
| 1fcd0ba2 SW |
240 | struct cdev *amr_dev_t; |
| 241 | struct lock amr_list_lock; | |
| 242 | ||
| 243 | struct sysctl_ctx_list amr_sysctl_ctx; | |
| 244 | struct sysctl_oid *amr_sysctl_tree; | |
| 984263bc MD |
245 | |
| 246 | /* controller type-specific support */ | |
| 247 | int amr_type; | |
| 248 | #define AMR_TYPE_QUARTZ (1<<0) | |
| 249 | #define AMR_IS_QUARTZ(sc) ((sc)->amr_type & AMR_TYPE_QUARTZ) | |
| 250 | #define AMR_TYPE_40LD (1<<1) | |
| 251 | #define AMR_IS_40LD(sc) ((sc)->amr_type & AMR_TYPE_40LD) | |
| 1fcd0ba2 SW |
252 | #define AMR_TYPE_SG64 (1<<2) |
| 253 | #define AMR_IS_SG64(sc) ((sc)->amr_type & AMR_TYPE_SG64) | |
| 254 | int (* amr_submit_command)(struct amr_command *ac); | |
| 984263bc MD |
255 | int (* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave); |
| 256 | int (*amr_poll_command)(struct amr_command *ac); | |
| 1fcd0ba2 | 257 | int (*amr_poll_command1)(struct amr_softc *sc, struct amr_command *ac); |
| 984263bc MD |
258 | int support_ext_cdb; /* greater than 10 byte cdb support */ |
| 259 | ||
| 260 | /* misc glue */ | |
| 1fcd0ba2 SW |
261 | device_t amr_pass; |
| 262 | int (*amr_cam_command)(struct amr_softc *sc, struct amr_command **acp); | |
| 984263bc | 263 | struct intr_config_hook amr_ich; /* wait-for-interrupts probe hook */ |
| 1fcd0ba2 SW |
264 | int amr_allow_vol_config; |
| 265 | int amr_linux_no_adapters; | |
| 266 | int amr_ld_del_supported; | |
| 267 | struct lock amr_hw_lock; | |
| 984263bc MD |
268 | }; |
| 269 | ||
| 270 | /* | |
| 271 | * Interface between bus connections and driver core. | |
| 272 | */ | |
| 273 | extern int amr_attach(struct amr_softc *sc); | |
| 274 | extern void amr_free(struct amr_softc *sc); | |
| 275 | extern int amr_flush(struct amr_softc *sc); | |
| 276 | extern int amr_done(struct amr_softc *sc); | |
| 277 | extern void amr_startio(struct amr_softc *sc); | |
| 278 | ||
| 279 | /* | |
| 280 | * Command buffer allocation. | |
| 281 | */ | |
| 282 | extern struct amr_command *amr_alloccmd(struct amr_softc *sc); | |
| 283 | extern void amr_releasecmd(struct amr_command *ac); | |
| 284 | ||
| 285 | /* | |
| 984263bc MD |
286 | * MegaRAID logical disk driver |
| 287 | */ | |
| 288 | struct amrd_softc | |
| 289 | { | |
| 290 | device_t amrd_dev; | |
| b13267a5 | 291 | cdev_t amrd_dev_t; |
| 984263bc MD |
292 | struct amr_softc *amrd_controller; |
| 293 | struct amr_logdrive *amrd_drive; | |
| 294 | struct disk amrd_disk; | |
| 295 | struct devstat amrd_stats; | |
| 296 | int amrd_unit; | |
| 984263bc MD |
297 | }; |
| 298 | ||
| 299 | /* | |
| 300 | * Interface between driver core and disk driver (should be using a bus?) | |
| 301 | */ | |
| 302 | extern int amr_submit_bio(struct amr_softc *sc, struct bio *bio); | |
| 1fcd0ba2 SW |
303 | extern int amr_dump_blocks(struct amr_softc *sc, int unit, u_int32_t lba, void *data, int blks); |
| 304 | extern void amrd_intr(void *data); | |
| 984263bc MD |
305 | |
| 306 | /******************************************************************************** | |
| 307 | * Enqueue/dequeue functions | |
| 308 | */ | |
| 309 | static __inline void | |
| 310 | amr_enqueue_bio(struct amr_softc *sc, struct bio *bio) | |
| 311 | { | |
| 1fcd0ba2 SW |
312 | |
| 313 | bioq_insert_tail(&sc->amr_bioq, bio); | |
| 984263bc MD |
314 | } |
| 315 | ||
| 316 | static __inline struct bio * | |
| 317 | amr_dequeue_bio(struct amr_softc *sc) | |
| 318 | { | |
| 319 | struct bio *bio; | |
| 984263bc | 320 | |
| 984263bc MD |
321 | if ((bio = bioq_first(&sc->amr_bioq)) != NULL) |
| 322 | bioq_remove(&sc->amr_bioq, bio); | |
| 984263bc MD |
323 | return(bio); |
| 324 | } | |
| 325 | ||
| 326 | static __inline void | |
| 1fcd0ba2 SW |
327 | amr_init_qhead(ac_qhead_t *head) |
| 328 | { | |
| 329 | ||
| 330 | STAILQ_INIT(head); | |
| 331 | } | |
| 332 | ||
| 333 | static __inline void | |
| 984263bc MD |
334 | amr_enqueue_ready(struct amr_command *ac) |
| 335 | { | |
| 1fcd0ba2 SW |
336 | |
| 337 | STAILQ_INSERT_TAIL(&ac->ac_sc->amr_ready, ac, ac_link); | |
| 984263bc MD |
338 | } |
| 339 | ||
| 340 | static __inline void | |
| 341 | amr_requeue_ready(struct amr_command *ac) | |
| 342 | { | |
| 1fcd0ba2 SW |
343 | |
| 344 | STAILQ_INSERT_HEAD(&ac->ac_sc->amr_ready, ac, ac_link); | |
| 984263bc MD |
345 | } |
| 346 | ||
| 347 | static __inline struct amr_command * | |
| 348 | amr_dequeue_ready(struct amr_softc *sc) | |
| 349 | { | |
| 350 | struct amr_command *ac; | |
| 984263bc | 351 | |
| 1fcd0ba2 SW |
352 | if ((ac = STAILQ_FIRST(&sc->amr_ready)) != NULL) |
| 353 | STAILQ_REMOVE_HEAD(&sc->amr_ready, ac_link); | |
| 984263bc MD |
354 | return(ac); |
| 355 | } | |
| 356 | ||
| 357 | static __inline void | |
| 1fcd0ba2 | 358 | amr_enqueue_completed(struct amr_command *ac, ac_qhead_t *head) |
| 984263bc | 359 | { |
| 1fcd0ba2 SW |
360 | |
| 361 | STAILQ_INSERT_TAIL(head, ac, ac_link); | |
| 984263bc MD |
362 | } |
| 363 | ||
| 364 | static __inline struct amr_command * | |
| 1fcd0ba2 | 365 | amr_dequeue_completed(struct amr_softc *sc, ac_qhead_t *head) |
| 984263bc MD |
366 | { |
| 367 | struct amr_command *ac; | |
| 984263bc | 368 | |
| 1fcd0ba2 SW |
369 | if ((ac = STAILQ_FIRST(head)) != NULL) |
| 370 | STAILQ_REMOVE_HEAD(head, ac_link); | |
| 984263bc MD |
371 | return(ac); |
| 372 | } | |
| 373 | ||
| 374 | static __inline void | |
| 375 | amr_enqueue_free(struct amr_command *ac) | |
| 376 | { | |
| 1fcd0ba2 SW |
377 | |
| 378 | STAILQ_INSERT_HEAD(&ac->ac_sc->amr_freecmds, ac, ac_link); | |
| 984263bc MD |
379 | } |
| 380 | ||
| 381 | static __inline struct amr_command * | |
| 382 | amr_dequeue_free(struct amr_softc *sc) | |
| 383 | { | |
| 384 | struct amr_command *ac; | |
| 984263bc | 385 | |
| 1fcd0ba2 SW |
386 | if ((ac = STAILQ_FIRST(&sc->amr_freecmds)) != NULL) |
| 387 | STAILQ_REMOVE_HEAD(&sc->amr_freecmds, ac_link); | |
| 984263bc MD |
388 | return(ac); |
| 389 | } |