1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _GHD_H 28 #define _GHD_H 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 36 #include <sys/types.h> 37 #include <sys/conf.h> 38 #include <sys/kmem.h> 39 #include <sys/ddi.h> 40 #include <sys/sunddi.h> 41 #include <sys/debug.h> 42 #include <sys/scsi/scsi.h> 43 44 #include "ghd_queue.h" /* linked list structures */ 45 #include "ghd_scsi.h" 46 #include "ghd_waitq.h" 47 #include "ghd_debug.h" 48 49 #ifndef TRUE 50 #define TRUE 1 51 #endif 52 53 #ifndef FALSE 54 #define FALSE 0 55 #endif 56 57 /* 58 * values for cmd_state: 59 */ 60 61 typedef enum { 62 GCMD_STATE_IDLE = 0, 63 GCMD_STATE_WAITQ, 64 GCMD_STATE_ACTIVE, 65 GCMD_STATE_DONEQ, 66 GCMD_STATE_ABORTING_CMD, 67 GCMD_STATE_ABORTING_DEV, 68 GCMD_STATE_RESETTING_DEV, 69 GCMD_STATE_RESETTING_BUS, 70 GCMD_STATE_HUNG, 71 GCMD_NSTATES 72 } cmdstate_t; 73 74 /* 75 * action codes for the HBA timeout function 76 */ 77 78 typedef enum { 79 GACTION_EARLY_TIMEOUT = 0, /* timed-out before started */ 80 GACTION_EARLY_ABORT, /* scsi_abort() before started */ 81 GACTION_ABORT_CMD, /* abort a specific request */ 82 GACTION_ABORT_DEV, /* abort everything on specifici dev */ 83 GACTION_RESET_TARGET, /* reset a specific dev */ 84 GACTION_RESET_BUS, /* reset the whole bus */ 85 GACTION_INCOMPLETE /* giving up on incomplete request */ 86 } gact_t; 87 88 /* 89 * types of ghd_timer_poll() invocations 90 */ 91 92 typedef enum { 93 GHD_TIMER_POLL_ALL = 0, /* time out all expired commands */ 94 GHD_TIMER_POLL_ONE /* time out one, let caller loop */ 95 } gtimer_poll_t; 96 97 /* 98 * the common portion of the Command Control Block 99 */ 100 101 typedef struct ghd_cmd { 102 L2el_t cmd_q; /* link for for done/active CCB Qs */ 103 cmdstate_t cmd_state; /* request's current state */ 104 ulong_t cmd_waitq_level; /* which wait Q this request is on */ 105 int cmd_flags; /* generic magic info */ 106 107 L2el_t cmd_timer_link; /* ccb timer doubly linked list */ 108 ulong_t cmd_start_time; /* lbolt at start of request */ 109 ulong_t cmd_timeout; /* how long to wait */ 110 111 opaque_t cmd_private; /* used by the HBA driver */ 112 void *cmd_pktp; /* request packet */ 113 gtgt_t *cmd_gtgtp; /* dev instance for this request */ 114 115 int cmd_dma_flags; 116 ddi_dma_handle_t cmd_dma_handle; 117 ddi_dma_win_t cmd_dmawin; 118 ddi_dma_seg_t cmd_dmaseg; 119 120 uint_t cmd_wcount; /* ddi_dma_attr: window count */ 121 uint_t cmd_windex; /* ddi_dma_attr: current window */ 122 uint_t cmd_ccount; /* ddi_dma_attr: cookie count */ 123 uint_t cmd_cindex; /* ddi_dma_attr: current cookie */ 124 125 long cmd_totxfer; /* # bytes transferred so far */ 126 ddi_dma_cookie_t cmd_first_cookie; 127 int use_first; 128 } gcmd_t; 129 130 131 /* definitions for cmd_flags */ 132 #define GCMDFLG_RESET_NOTIFY 1 /* command is a reset notification */ 133 134 /* 135 * Initialize the gcmd_t structure 136 */ 137 138 #define GHD_GCMD_INIT(gcmdp, cmdp, gtgtp) \ 139 (L2_INIT(&(gcmdp)->cmd_q), \ 140 L2_INIT(&(gcmdp)->cmd_timer_link), \ 141 (gcmdp)->cmd_private = (cmdp), \ 142 (gcmdp)->cmd_gtgtp = (gtgtp) \ 143 ) 144 145 146 /* 147 * CMD/CCB timer config structure - one per HBA driver module 148 */ 149 typedef struct tmr_conf { 150 kmutex_t t_mutex; /* mutex to protect t_ccc_listp */ 151 timeout_id_t t_timeout_id; /* handle for timeout() function */ 152 long t_ticks; /* periodic timeout in clock ticks */ 153 int t_refs; /* reference count */ 154 struct cmd_ctl *t_ccc_listp; /* control struct list, one per HBA */ 155 } tmr_t; 156 157 158 159 /* 160 * CMD/CCB timer control structure - one per HBA instance (per board) 161 */ 162 typedef struct cmd_ctl { 163 struct cmd_ctl *ccc_nextp; /* list of control structs */ 164 struct tmr_conf *ccc_tmrp; /* back ptr to config struct */ 165 char *ccc_label; /* name of this HBA driver */ 166 167 kmutex_t ccc_activel_mutex; /* mutex to protect list ... */ 168 L2el_t ccc_activel; /* ... list of active CMD/CCBs */ 169 170 dev_info_t *ccc_hba_dip; 171 ddi_iblock_cookie_t ccc_iblock; 172 ddi_softintr_t ccc_soft_id; /* ID for timeout softintr */ 173 174 kmutex_t ccc_hba_mutex; /* mutex for HBA soft-state */ 175 int ccc_hba_pollmode; /* FLAG_NOINTR mode active? */ 176 177 L1_t ccc_devs; /* unsorted list of attached devs */ 178 kmutex_t ccc_waitq_mutex; /* mutex to protect device wait Qs */ 179 Q_t ccc_waitq; /* the HBA's wait queue */ 180 clock_t ccc_waitq_freezetime; /* time the waitq was frozen, ticks */ 181 uint_t ccc_waitq_freezedelay; /* delta time until waitq thaws, ms */ 182 183 ddi_softintr_t ccc_doneq_softid; /* ID for doneq softintr */ 184 kmutex_t ccc_doneq_mutex; /* mutex to protect the doneq */ 185 L2el_t ccc_doneq; /* completed cmd_t's */ 186 187 void *ccc_hba_handle; 188 int (*ccc_ccballoc)(); /* alloc/init gcmd and ccb */ 189 void (*ccc_ccbfree)(); 190 void (*ccc_sg_func)(); 191 int (*ccc_hba_start)(void *handle, gcmd_t *); 192 void (*ccc_hba_complete)(void *handle, gcmd_t *, int); 193 void (*ccc_process_intr)(void *handle, void *intr_status); 194 int (*ccc_get_status)(void *handle, void *intr_status); 195 int (*ccc_timeout_func)(void *handle, gcmd_t *cmdp, gtgt_t *gtgtp, 196 gact_t action, int calltype); 197 void (*ccc_hba_reset_notify_callback)(gtgt_t *gtgtp, 198 void (*callback)(caddr_t), 199 caddr_t arg); 200 L2el_t ccc_reset_notify_list; /* list of reset notifications */ 201 kmutex_t ccc_reset_notify_mutex; /* and a mutex to protect it */ 202 char ccc_timeout_pending; /* timeout Q's softintr is triggered */ 203 char ccc_waitq_frozen; /* ccc_waitq_freezetime non-null */ 204 char ccc_waitq_held; /* frozen, but no freezetime */ 205 } ccc_t; 206 207 #define GHBA_QHEAD(cccp) ((cccp)->ccc_waitq.Q_qhead) 208 #define GHBA_MAXACTIVE(cccp) ((cccp)->ccc_waitq.Q_maxactive) 209 #define GHBA_NACTIVE(cccp) ((cccp)->ccc_waitq.Q_nactive) 210 211 /* Initialize the HBA's list headers */ 212 #define CCCP_INIT(cccp) { \ 213 L1HEADER_INIT(&(cccp)->ccc_devs); \ 214 L2_INIT(&(cccp)->ccc_doneq); \ 215 L2_INIT(&(cccp)->ccc_reset_notify_list); \ 216 } 217 218 219 #define CCCP2GDEVP(cccp) \ 220 (L1_EMPTY(&(cccp)->ccc_devs) \ 221 ? (gdev_t *)NULL \ 222 : (gdev_t *)((cccp)->ccc_devs.l1_headp->le_datap)) 223 224 225 /* 226 * reset_notify handling: these elements are on the ccc_t's 227 * reset_notify_list, one for each notification requested. The 228 * gtgtp isn't needed except for debug. 229 */ 230 231 typedef struct ghd_reset_notify_list { 232 gtgt_t *gtgtp; 233 void (*callback)(caddr_t); 234 caddr_t arg; 235 L2el_t l2_link; 236 } ghd_reset_notify_list_t; 237 238 /* ******************************************************************* */ 239 240 #include "ghd_scsa.h" 241 #include "ghd_dma.h" 242 243 /* 244 * GHD Entry Points 245 */ 246 void ghd_complete(ccc_t *cccp, gcmd_t *cmdp); 247 void ghd_doneq_put_head(ccc_t *cccp, gcmd_t *cmdp); 248 void ghd_doneq_put_tail(ccc_t *cccp, gcmd_t *cmdp); 249 250 int ghd_intr(ccc_t *cccp, void *status); 251 int ghd_register(char *, ccc_t *, dev_info_t *, int, void *hba_handle, 252 int (*ccc_ccballoc)(gtgt_t *, gcmd_t *, int, int, 253 int, int), 254 void (*ccc_ccbfree)(gcmd_t *), 255 void (*ccc_sg_func)(gcmd_t *, ddi_dma_cookie_t *, 256 int, int), 257 int (*hba_start)(void *, gcmd_t *), 258 void (*hba_complete)(void *, gcmd_t *, int), 259 uint_t (*int_handler)(caddr_t), 260 int (*get_status)(void *, void *), 261 void (*process_intr)(void *, void *), 262 int (*timeout_func)(void *, gcmd_t *, gtgt_t *, 263 gact_t, int), 264 tmr_t *tmrp, 265 void (*hba_reset_notify_callback)(gtgt_t *, 266 void (*)(caddr_t), caddr_t)); 267 void ghd_unregister(ccc_t *cccp); 268 269 int ghd_transport(ccc_t *cccp, gcmd_t *cmdp, gtgt_t *gtgtp, 270 ulong_t timeout, int polled, void *intr_status); 271 272 int ghd_tran_abort(ccc_t *cccp, gcmd_t *cmdp, gtgt_t *gtgtp, 273 void *intr_status); 274 int ghd_tran_abort_lun(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status); 275 int ghd_tran_reset_target(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status); 276 int ghd_tran_reset_bus(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status); 277 int ghd_reset_notify(ccc_t *cccp, gtgt_t *gtgtp, int flag, 278 void (*callback)(caddr_t), caddr_t arg); 279 void ghd_freeze_waitq(ccc_t *cccp, int delay); 280 void ghd_trigger_reset_notify(ccc_t *cccp); 281 282 void ghd_queue_hold(ccc_t *cccp); 283 void ghd_queue_unhold(ccc_t *cccp); 284 285 /* 286 * Allocate a gcmd_t wrapper and HBA private area 287 */ 288 gcmd_t *ghd_gcmd_alloc(gtgt_t *gtgtp, int ccblen, int sleep); 289 290 /* 291 * Free the gcmd_t wrapper and HBA private area 292 */ 293 void ghd_gcmd_free(gcmd_t *gcmdp); 294 295 296 /* 297 * GHD CMD/CCB timer Entry points 298 */ 299 300 int ghd_timer_attach(ccc_t *cccp, tmr_t *tmrp, 301 int (*timeout_func)(void *handle, gcmd_t *, gtgt_t *, 302 gact_t, int)); 303 void ghd_timer_detach(ccc_t *cccp); 304 void ghd_timer_fini(tmr_t *tmrp); 305 void ghd_timer_init(tmr_t *tmrp, long ticks); 306 void ghd_timer_newstate(ccc_t *cccp, gcmd_t *cmdp, gtgt_t *gtgtp, 307 gact_t action, int calltype); 308 void ghd_timer_poll(ccc_t *cccp, gtimer_poll_t calltype); 309 void ghd_timer_start(ccc_t *cccp, gcmd_t *cmdp, long cmd_timeout); 310 void ghd_timer_stop(ccc_t *cccp, gcmd_t *cmdp); 311 312 313 /* 314 * Wait queue utility routines 315 */ 316 317 gtgt_t *ghd_target_init(dev_info_t *, dev_info_t *, ccc_t *, size_t, 318 void *, ushort_t, uchar_t); 319 void ghd_target_free(dev_info_t *, dev_info_t *, ccc_t *, gtgt_t *); 320 void ghd_waitq_shuffle_up(ccc_t *, gdev_t *); 321 void ghd_waitq_delete(ccc_t *, gcmd_t *); 322 int ghd_waitq_process_and_mutex_hold(ccc_t *); 323 void ghd_waitq_process_and_mutex_exit(ccc_t *); 324 325 326 /* 327 * The values for the calltype arg for the ghd_timer_newstate() function, 328 * and the HBA timeout-action function (ccc_timeout_func) 329 */ 330 331 #define GHD_TGTREQ 0 332 #define GHD_TIMEOUT 1 333 334 /* ******************************************************************* */ 335 336 /* 337 * specify GHD_INLINE to get optimized versions 338 */ 339 #define GHD_INLINE 1 340 #if defined(GHD_DEBUG) || defined(DEBUG) || defined(__lint) 341 #undef GHD_INLINE 342 #endif 343 344 #if defined(GHD_INLINE) 345 #define GHD_COMPLETE(cccp, gcmpd) GHD_COMPLETE_INLINE(cccp, gcmdp) 346 #define GHD_TIMER_STOP(cccp, gcmdp) GHD_TIMER_STOP_INLINE(cccp, gcmdp) 347 #define GHD_DONEQ_PUT_HEAD(cccp, gcmdp) GHD_DONEQ_PUT_HEAD_INLINE(cccp, gcmdp) 348 #define GHD_DONEQ_PUT_TAIL(cccp, gcmdp) GHD_DONEQ_PUT_TAIL_INLINE(cccp, gcmdp) 349 #else 350 #define GHD_COMPLETE(cccp, gcmpd) ghd_complete(cccp, gcmdp) 351 #define GHD_TIMER_STOP(cccp, gcmdp) ghd_timer_stop(cccp, gcmdp) 352 #define GHD_DONEQ_PUT_HEAD(cccp, gcmdp) ghd_doneq_put_head(cccp, gcmdp) 353 #define GHD_DONEQ_PUT_TAIL(cccp, gcmdp) ghd_doneq_put_tail(cccp, gcmdp) 354 #endif 355 356 /* 357 * request is complete, stop the request timer and add to doneq 358 */ 359 #define GHD_COMPLETE_INLINE(cccp, gcmdp) \ 360 { \ 361 ghd_waitq_delete(cccp, gcmdp); \ 362 (gcmdp)->cmd_state = GCMD_STATE_DONEQ; \ 363 GHD_TIMER_STOP((cccp), (gcmdp)); \ 364 GHD_DONEQ_PUT_TAIL((cccp), (gcmdp)); \ 365 } 366 367 #define GHD_TIMER_STOP_INLINE(cccp, gcmdp) \ 368 { \ 369 mutex_enter(&(cccp)->ccc_activel_mutex);\ 370 L2_delete(&(gcmdp)->cmd_timer_link); \ 371 mutex_exit(&(cccp)->ccc_activel_mutex); \ 372 } 373 374 /* 375 * mark the request done and append it to the head of the doneq 376 */ 377 #define GHD_DONEQ_PUT_HEAD_INLINE(cccp, gcmdp) \ 378 { \ 379 kmutex_t *doneq_mutexp = &(cccp)->ccc_doneq_mutex; \ 380 \ 381 mutex_enter(doneq_mutexp); \ 382 (gcmdp)->cmd_state = GCMD_STATE_DONEQ; \ 383 L2_add_head(&(cccp)->ccc_doneq, &(gcmdp)->cmd_q, (gcmdp)); \ 384 if (!(cccp)->ccc_hba_pollmode) \ 385 ddi_trigger_softintr((cccp)->ccc_doneq_softid); \ 386 mutex_exit(doneq_mutexp); \ 387 } 388 389 /* 390 * mark the request done and append it to the tail of the doneq 391 */ 392 #define GHD_DONEQ_PUT_TAIL_INLINE(cccp, gcmdp) \ 393 { \ 394 kmutex_t *doneq_mutexp = &(cccp)->ccc_doneq_mutex; \ 395 \ 396 mutex_enter(doneq_mutexp); \ 397 (gcmdp)->cmd_state = GCMD_STATE_DONEQ; \ 398 L2_add(&(cccp)->ccc_doneq, &(gcmdp)->cmd_q, (gcmdp)); \ 399 if (!(cccp)->ccc_hba_pollmode) \ 400 ddi_trigger_softintr((cccp)->ccc_doneq_softid); \ 401 mutex_exit(doneq_mutexp); \ 402 } 403 404 /* ******************************************************************* */ 405 406 /* 407 * These are shortcut macros for linkages setup by GHD 408 */ 409 410 /* 411 * (gcmd_t *) to (struct scsi_pkt *) 412 */ 413 #define GCMDP2PKTP(gcmdp) ((gcmdp)->cmd_pktp) 414 415 /* 416 * (gcmd_t *) to (gtgt_t *) 417 */ 418 #define GCMDP2GTGTP(gcmdp) ((gcmdp)->cmd_gtgtp) 419 420 /* 421 * (gcmd_t *) to (gdev_t *) 422 */ 423 #define GCMDP2GDEVP(gcmdp) ((gcmdp)->cmd_gtgtp->gt_gdevp) 424 425 /* 426 * (gcmd_t *) to (ccc_t *) 427 */ 428 #define GCMDP2CCCP(gcmdp) (GCMDP2GTGTP(gcmdp)->gt_ccc) 429 430 /* 431 * (struct scsi_pkt *) to (gcmd_t *) 432 */ 433 #define PKTP2GCMDP(pktp) ((gcmd_t *)(pktp)->pkt_ha_private) 434 435 436 /* These are shortcut macros for linkages setup by SCSA */ 437 438 /* 439 * (struct scsi_address *) to (scsi_hba_tran *) 440 */ 441 #define ADDR2TRAN(ap) ((ap)->a_hba_tran) 442 443 /* 444 * (struct scsi_device *) to (scsi_address *) 445 */ 446 #define SDEV2ADDR(sdp) (&(sdp)->sd_address) 447 448 /* 449 * (struct scsi_device *) to (scsi_hba_tran *) 450 */ 451 #define SDEV2TRAN(sdp) ADDR2TRAN(SDEV2ADDR(sdp)) 452 453 /* 454 * (struct scsi_pkt *) to (scsi_hba_tran *) 455 */ 456 #define PKTP2TRAN(pktp) ADDR2TRAN(&(pktp)->pkt_address) 457 458 /* 459 * (scsi_hba_tran_t *) to (per-target-soft-state *) 460 */ 461 #define TRAN2GTGTP(tranp) ((gtgt_t *)((tranp)->tran_tgt_private)) 462 463 /* 464 * (struct scsi_device *) to (per-target-soft-state *) 465 */ 466 #define SDEV2GTGTP(sd) TRAN2GTGTP(SDEV2TRAN(sd)) 467 468 /* 469 * (struct scsi_pkt *) to (per-target-soft-state *) 470 */ 471 #define PKTP2GTGTP(pktp) TRAN2GTGTP(PKTP2TRAN(pktp)) 472 473 474 /* 475 * (scsi_hba_tran_t *) to (per-HBA-soft-state *) 476 */ 477 #define TRAN2HBA(tranp) ((tranp)->tran_hba_private) 478 479 480 /* 481 * (struct scsi_device *) to (per-HBA-soft-state *) 482 */ 483 #define SDEV2HBA(sd) TRAN2HBA(SDEV2TRAN(sd)) 484 485 /* 486 * (struct scsi_address *) to (per-target-soft-state *) 487 */ 488 #define ADDR2GTGTP(ap) TRAN2GTGTP(ADDR2TRAN(ap)) 489 490 /* ******************************************************************* */ 491 492 493 #ifdef __cplusplus 494 } 495 #endif 496 497 #endif /* _GHD_H */ 498