1 /*- 2 * Copyright (c) 2006 IronPort Systems 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 /*- 27 * Copyright (c) 2007 LSI Corp. 28 * Copyright (c) 2007 Rajesh Prabhakaran. 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 * 40 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50 * SUCH DAMAGE. 51 * 52 * $FreeBSD: src/sys/dev/mfi/mfivar.h,v 1.13 2009/07/10 08:18:08 scottl Exp $ 53 */ 54 55 #ifndef _MFIVAR_H 56 #define _MFIVAR_H 57 58 #include <sys/devicestat.h> 59 #include <sys/disk.h> 60 #include <sys/eventhandler.h> 61 #include <sys/lock.h> 62 #include <sys/sysctl.h> 63 64 /* 65 * SCSI structures and definitions are used from here, but no linking 66 * requirements are made to CAM. 67 */ 68 #include <bus/cam/scsi/scsi_all.h> 69 70 struct mfi_hwcomms { 71 uint32_t hw_pi; 72 uint32_t hw_ci; 73 uint32_t hw_reply_q[1]; 74 }; 75 76 struct mfi_softc; 77 struct disk; 78 struct ccb_hdr; 79 80 struct mfi_command { 81 TAILQ_ENTRY(mfi_command) cm_link; 82 time_t cm_timestamp; 83 struct mfi_softc *cm_sc; 84 union mfi_frame *cm_frame; 85 uint32_t cm_frame_busaddr; 86 struct mfi_sense *cm_sense; 87 uint32_t cm_sense_busaddr; 88 bus_dmamap_t cm_dmamap; 89 union mfi_sgl *cm_sg; 90 void *cm_data; 91 int cm_len; 92 int cm_total_frame_size; 93 int cm_extra_frames; 94 int cm_flags; 95 #define MFI_CMD_MAPPED (1<<0) 96 #define MFI_CMD_DATAIN (1<<1) 97 #define MFI_CMD_DATAOUT (1<<2) 98 #define MFI_CMD_COMPLETED (1<<3) 99 #define MFI_CMD_POLLED (1<<4) 100 #define MFI_ON_MFIQ_FREE (1<<5) 101 #define MFI_ON_MFIQ_READY (1<<6) 102 #define MFI_ON_MFIQ_BUSY (1<<7) 103 #define MFI_ON_MFIQ_MASK ((1<<5)|(1<<6)|(1<<7)) 104 int cm_aen_abort; 105 void (* cm_complete)(struct mfi_command *cm); 106 void *cm_private; 107 int cm_index; 108 int cm_error; 109 }; 110 111 struct mfi_disk { 112 TAILQ_ENTRY(mfi_disk) ld_link; 113 device_t ld_dev; 114 int ld_id; 115 int ld_unit; 116 struct mfi_softc *ld_controller; 117 struct mfi_ld_info *ld_info; 118 struct disk ld_disk; 119 struct devstat ld_devstat; 120 int ld_flags; 121 #define MFI_DISK_FLAGS_OPEN 0x01 122 #define MFI_DISK_FLAGS_DISABLED 0x02 123 }; 124 125 struct mfi_aen { 126 TAILQ_ENTRY(mfi_aen) aen_link; 127 struct proc *p; 128 }; 129 130 struct mfi_softc { 131 device_t mfi_dev; 132 int mfi_flags; 133 #define MFI_FLAGS_SG64 (1<<0) 134 #define MFI_FLAGS_QFRZN (1<<1) 135 #define MFI_FLAGS_OPEN (1<<2) 136 #define MFI_FLAGS_STOP (1<<3) 137 #define MFI_FLAGS_1064R (1<<4) 138 #define MFI_FLAGS_1078 (1<<5) 139 #define MFI_FLAGS_GEN2 (1<<6) 140 141 struct mfi_hwcomms *mfi_comms; 142 TAILQ_HEAD(,mfi_command) mfi_free; 143 TAILQ_HEAD(,mfi_command) mfi_ready; 144 TAILQ_HEAD(,mfi_command) mfi_busy; 145 struct bio_queue_head mfi_bioq; 146 struct mfi_qstat mfi_qstat[MFIQ_COUNT]; 147 148 struct resource *mfi_regs_resource; 149 bus_space_handle_t mfi_bhandle; 150 bus_space_tag_t mfi_btag; 151 int mfi_regs_rid; 152 153 bus_dma_tag_t mfi_parent_dmat; 154 bus_dma_tag_t mfi_buffer_dmat; 155 156 bus_dma_tag_t mfi_comms_dmat; 157 bus_dmamap_t mfi_comms_dmamap; 158 uint32_t mfi_comms_busaddr; 159 160 bus_dma_tag_t mfi_frames_dmat; 161 bus_dmamap_t mfi_frames_dmamap; 162 uint32_t mfi_frames_busaddr; 163 union mfi_frame *mfi_frames; 164 165 TAILQ_HEAD(,mfi_aen) mfi_aen_pids; 166 struct mfi_command *mfi_aen_cm; 167 uint32_t mfi_aen_triggered; 168 uint32_t mfi_poll_waiting; 169 struct kqinfo mfi_kq; 170 int mfi_delete_busy_volumes; 171 int mfi_keep_deleted_volumes; 172 int mfi_detaching; 173 174 bus_dma_tag_t mfi_sense_dmat; 175 bus_dmamap_t mfi_sense_dmamap; 176 uint32_t mfi_sense_busaddr; 177 struct mfi_sense *mfi_sense; 178 179 struct resource *mfi_irq; 180 void *mfi_intr; 181 int mfi_irq_rid; 182 183 struct intr_config_hook mfi_ich; 184 eventhandler_tag eh; 185 186 /* 187 * Allocation for the command array. Used as an indexable array to 188 * recover completed commands. 189 */ 190 struct mfi_command *mfi_commands; 191 /* 192 * How many commands were actually allocated 193 */ 194 int mfi_total_cmds; 195 /* 196 * How many commands the firmware can handle. Also how big the reply 197 * queue is, minus 1. 198 */ 199 int mfi_max_fw_cmds; 200 /* 201 * How many S/G elements we'll ever actually use 202 */ 203 int mfi_max_sge; 204 /* 205 * How many bytes a compound frame is, including all of the extra frames 206 * that are used for S/G elements. 207 */ 208 int mfi_cmd_size; 209 /* 210 * How large an S/G element is. Used to calculate the number of single 211 * frames in a command. 212 */ 213 int mfi_sge_size; 214 /* 215 * Max number of sectors that the firmware allows 216 */ 217 uint32_t mfi_max_io; 218 219 TAILQ_HEAD(,mfi_disk) mfi_ld_tqh; 220 eventhandler_tag mfi_eh; 221 struct cdev *mfi_cdev; 222 223 TAILQ_HEAD(, ccb_hdr) mfi_cam_ccbq; 224 struct mfi_command * (* mfi_cam_start)(void *); 225 struct callout mfi_watchdog_callout; 226 struct lock mfi_io_lock; 227 struct lock mfi_config_lock; 228 229 struct sysctl_ctx_list mfi_sysctl_ctx; 230 struct sysctl_oid *mfi_sysctl_tree; 231 232 /* Controller type specific interfaces */ 233 void (*mfi_enable_intr)(struct mfi_softc *sc); 234 int32_t (*mfi_read_fw_status)(struct mfi_softc *sc); 235 int (*mfi_check_clear_intr)(struct mfi_softc *sc); 236 void (*mfi_issue_cmd)(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt); 237 }; 238 239 extern int mfi_attach(struct mfi_softc *); 240 extern void mfi_free(struct mfi_softc *); 241 extern int mfi_shutdown(struct mfi_softc *); 242 extern void mfi_startio(struct mfi_softc *); 243 extern void mfi_disk_complete(struct bio *); 244 extern int mfi_disk_disable(struct mfi_disk *); 245 extern void mfi_disk_enable(struct mfi_disk *); 246 extern int mfi_dump_blocks(struct mfi_softc *, int id, uint64_t, void *, int); 247 248 #define MFIQ_ADD(sc, qname) \ 249 do { \ 250 struct mfi_qstat *qs; \ 251 \ 252 qs = &(sc)->mfi_qstat[qname]; \ 253 qs->q_length++; \ 254 if (qs->q_length > qs->q_max) \ 255 qs->q_max = qs->q_length; \ 256 } while (0) 257 258 #define MFIQ_REMOVE(sc, qname) (sc)->mfi_qstat[qname].q_length-- 259 260 #define MFIQ_INIT(sc, qname) \ 261 do { \ 262 sc->mfi_qstat[qname].q_length = 0; \ 263 sc->mfi_qstat[qname].q_max = 0; \ 264 } while (0) 265 266 #define MFIQ_COMMAND_QUEUE(name, index) \ 267 static __inline void \ 268 mfi_initq_ ## name (struct mfi_softc *sc) \ 269 { \ 270 TAILQ_INIT(&sc->mfi_ ## name); \ 271 MFIQ_INIT(sc, index); \ 272 } \ 273 static __inline void \ 274 mfi_enqueue_ ## name (struct mfi_command *cm) \ 275 { \ 276 if ((cm->cm_flags & MFI_ON_MFIQ_MASK) != 0) { \ 277 kprintf("command %p is on another queue, " \ 278 "flags = %#x\n", cm, cm->cm_flags); \ 279 panic("command is on another queue"); \ 280 } \ 281 TAILQ_INSERT_TAIL(&cm->cm_sc->mfi_ ## name, cm, cm_link); \ 282 cm->cm_flags |= MFI_ON_ ## index; \ 283 MFIQ_ADD(cm->cm_sc, index); \ 284 } \ 285 static __inline void \ 286 mfi_requeue_ ## name (struct mfi_command *cm) \ 287 { \ 288 if ((cm->cm_flags & MFI_ON_MFIQ_MASK) != 0) { \ 289 kprintf("command %p is on another queue, " \ 290 "flags = %#x\n", cm, cm->cm_flags); \ 291 panic("command is on another queue"); \ 292 } \ 293 TAILQ_INSERT_HEAD(&cm->cm_sc->mfi_ ## name, cm, cm_link); \ 294 cm->cm_flags |= MFI_ON_ ## index; \ 295 MFIQ_ADD(cm->cm_sc, index); \ 296 } \ 297 static __inline struct mfi_command * \ 298 mfi_dequeue_ ## name (struct mfi_softc *sc) \ 299 { \ 300 struct mfi_command *cm; \ 301 \ 302 if ((cm = TAILQ_FIRST(&sc->mfi_ ## name)) != NULL) { \ 303 if ((cm->cm_flags & MFI_ON_ ## index) == 0) { \ 304 kprintf("command %p not in queue, " \ 305 "flags = %#x, bit = %#x\n", cm, \ 306 cm->cm_flags, MFI_ON_ ## index); \ 307 panic("command not in queue"); \ 308 } \ 309 TAILQ_REMOVE(&sc->mfi_ ## name, cm, cm_link); \ 310 cm->cm_flags &= ~MFI_ON_ ## index; \ 311 MFIQ_REMOVE(sc, index); \ 312 } \ 313 return (cm); \ 314 } \ 315 static __inline void \ 316 mfi_remove_ ## name (struct mfi_command *cm) \ 317 { \ 318 if ((cm->cm_flags & MFI_ON_ ## index) == 0) { \ 319 kprintf("command %p not in queue, flags = %#x, " \ 320 "bit = %#x\n", cm, cm->cm_flags, \ 321 MFI_ON_ ## index); \ 322 panic("command not in queue"); \ 323 } \ 324 TAILQ_REMOVE(&cm->cm_sc->mfi_ ## name, cm, cm_link); \ 325 cm->cm_flags &= ~MFI_ON_ ## index; \ 326 MFIQ_REMOVE(cm->cm_sc, index); \ 327 } \ 328 struct hack 329 330 MFIQ_COMMAND_QUEUE(free, MFIQ_FREE); 331 MFIQ_COMMAND_QUEUE(ready, MFIQ_READY); 332 MFIQ_COMMAND_QUEUE(busy, MFIQ_BUSY); 333 334 static __inline void 335 mfi_initq_bio(struct mfi_softc *sc) 336 { 337 bioq_init(&sc->mfi_bioq); 338 MFIQ_INIT(sc, MFIQ_BIO); 339 } 340 341 static __inline void 342 mfi_enqueue_bio(struct mfi_softc *sc, struct bio *bp) 343 { 344 bioq_insert_tail(&sc->mfi_bioq, bp); 345 MFIQ_ADD(sc, MFIQ_BIO); 346 } 347 348 static __inline struct bio * 349 mfi_dequeue_bio(struct mfi_softc *sc) 350 { 351 struct bio *bp; 352 353 if ((bp = bioq_first(&sc->mfi_bioq)) != NULL) { 354 bioq_remove(&sc->mfi_bioq, bp); 355 MFIQ_REMOVE(sc, MFIQ_BIO); 356 } 357 return (bp); 358 } 359 360 static __inline void 361 mfi_print_sense(struct mfi_softc *sc, void *sense) 362 { 363 int error, key, asc, ascq; 364 365 scsi_extract_sense((struct scsi_sense_data *)sense, 366 &error, &key, &asc, &ascq); 367 device_printf(sc->mfi_dev, "sense error %d, sense_key %d, " 368 "asc %d, ascq %d\n", error, key, asc, ascq); 369 } 370 371 372 #define MFI_WRITE4(sc, reg, val) bus_space_write_4((sc)->mfi_btag, \ 373 sc->mfi_bhandle, (reg), (val)) 374 #define MFI_READ4(sc, reg) bus_space_read_4((sc)->mfi_btag, \ 375 (sc)->mfi_bhandle, (reg)) 376 #define MFI_WRITE2(sc, reg, val) bus_space_write_2((sc)->mfi_btag, \ 377 sc->mfi_bhandle, (reg), (val)) 378 #define MFI_READ2(sc, reg) bus_space_read_2((sc)->mfi_btag, \ 379 (sc)->mfi_bhandle, (reg)) 380 #define MFI_WRITE1(sc, reg, val) bus_space_write_1((sc)->mfi_btag, \ 381 sc->mfi_bhandle, (reg), (val)) 382 #define MFI_READ1(sc, reg) bus_space_read_1((sc)->mfi_btag, \ 383 (sc)->mfi_bhandle, (reg)) 384 385 MALLOC_DECLARE(M_MFIBUF); 386 387 #define MFI_CMD_TIMEOUT 30 388 #define MFI_MAXPHYS (128 * 1024) 389 390 #ifdef MFI_DEBUG 391 extern void mfi_print_cmd(struct mfi_command *cm); 392 extern void mfi_dump_cmds(struct mfi_softc *sc); 393 extern void mfi_validate_sg(struct mfi_softc *, struct mfi_command *, const char *, int ); 394 #define MFI_PRINT_CMD(cm) mfi_print_cmd(cm) 395 #define MFI_DUMP_CMDS(sc) mfi_dump_cmds(sc) 396 #define MFI_VALIDATE_CMD(sc, cm) mfi_validate_sg(sc, cm, __FUNCTION__, __LINE__) 397 #else 398 #define MFI_PRINT_CMD(cm) 399 #define MFI_DUMP_CMDS(sc) 400 #define MFI_VALIDATE_CMD(sc, cm) 401 #endif 402 403 extern void mfi_release_command(struct mfi_command *cm); 404 405 #endif /* _MFIVAR_H */ 406