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 2005 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 /* 90 * the common portion of the Command Control Block 91 */ 92 93 typedef struct ghd_cmd { 94 L2el_t cmd_q; /* link for for done/active CCB Qs */ 95 cmdstate_t cmd_state; /* request's current state */ 96 uint32_t cmd_waitq_level; /* which wait Q this request is on */ 97 98 L2el_t cmd_timer_link; /* ccb timer doubly linked list */ 99 clock_t cmd_start_time; /* lbolt at start of request */ 100 clock_t cmd_timeout; /* how long to wait */ 101 102 opaque_t cmd_private; /* used by the HBA driver */ 103 void *cmd_pktp; /* request packet */ 104 gtgt_t *cmd_gtgtp; /* dev instance for this request */ 105 106 ddi_dma_handle_t cmd_dma_handle; 107 ddi_dma_win_t cmd_dmawin; 108 ddi_dma_seg_t cmd_dmaseg; 109 int cmd_dma_flags; 110 long cmd_totxfer; 111 long cmd_resid; 112 } gcmd_t; 113 114 115 116 117 /* 118 * Initialize the gcmd_t structure 119 */ 120 121 #define GHD_GCMD_INIT(gcmdp, cmdp, gtgtp) \ 122 (L2_INIT(&(gcmdp)->cmd_q), \ 123 L2_INIT(&(gcmdp)->cmd_timer_link), \ 124 (gcmdp)->cmd_private = (cmdp), \ 125 (gcmdp)->cmd_gtgtp = (gtgtp) \ 126 ) 127 128 129 /* 130 * CMD/CCB timer config structure - one per HBA driver module 131 */ 132 typedef struct tmr_conf { 133 kmutex_t t_mutex; /* mutex to protect t_ccc_listp */ 134 timeout_id_t t_timeout_id; /* handle for timeout() function */ 135 clock_t t_ticks; /* periodic timeout in clock ticks */ 136 int t_refs; /* reference count */ 137 struct cmd_ctl *t_ccc_listp; /* control struct list, one per HBA */ 138 } tmr_t; 139 _NOTE(MUTEX_PROTECTS_DATA(tmr_t::t_mutex, tmr_t::t_ccc_listp)) 140 _NOTE(MUTEX_PROTECTS_DATA(tmr_t::t_mutex, tmr_t::t_timeout_id)) 141 _NOTE(MUTEX_PROTECTS_DATA(tmr_t::t_mutex, tmr_t::t_refs)) 142 143 144 145 /* 146 * CMD/CCB timer control structure - one per HBA instance (per board) 147 */ 148 typedef struct cmd_ctl { 149 struct cmd_ctl *ccc_nextp; /* list of control structs */ 150 struct tmr_conf *ccc_tmrp; /* back ptr to config struct */ 151 char *ccc_label; /* name of this HBA driver */ 152 int ccc_chno; /* Channle number */ 153 154 kmutex_t ccc_activel_mutex; /* mutex to protect list ... */ 155 L2el_t ccc_activel; /* ... list of active CMD/CCBs */ 156 157 dev_info_t *ccc_hba_dip; 158 ddi_iblock_cookie_t ccc_iblock; 159 ddi_softintr_t ccc_soft_id; /* ID for timeout softintr */ 160 161 kmutex_t ccc_hba_mutex; /* mutex for HBA soft-state */ 162 int ccc_hba_pollmode; /* FLAG_NOINTR mode active? */ 163 164 L1_t ccc_devs; /* unsorted list of attached devs */ 165 kmutex_t ccc_waitq_mutex; /* mutex to protect device wait Qs */ 166 Q_t ccc_waitq; /* the HBA's wait queue */ 167 168 ddi_softintr_t ccc_doneq_softid; /* ID for doneq softintr */ 169 kmutex_t ccc_doneq_mutex; /* mutex to protect the doneq */ 170 L2el_t ccc_doneq; /* completed cmd_t's */ 171 172 void *ccc_hba_handle; 173 int (*ccc_ccballoc)(); /* alloc/init gcmd and ccb */ 174 void (*ccc_ccbfree)(); 175 void (*ccc_sg_func)(); 176 int (*ccc_hba_start)(void *handle, gcmd_t *); 177 void (*ccc_hba_complete)(void *handle, gcmd_t *, int); 178 void (*ccc_process_intr)(void *handle, void *intr_status, int chno); 179 int (*ccc_get_status)(void *handle, void *intr_status, int chno); 180 int (*ccc_timeout_func)(void *handle, gcmd_t *cmdp, gtgt_t *gtgtp, 181 gact_t action, int calltype); 182 } ccc_t; 183 _NOTE(MUTEX_PROTECTS_DATA(cmd_ctl::ccc_activel_mutex, cmd_ctl::ccc_activel)) 184 _NOTE(MUTEX_PROTECTS_DATA(cmd_ctl::ccc_hba_mutex, cmd_ctl::ccc_hba_dip)) 185 _NOTE(DATA_READABLE_WITHOUT_LOCK(cmd_ctl::ccc_hba_dip)) 186 _NOTE(MUTEX_PROTECTS_DATA(cmd_ctl::ccc_waitq_mutex, cmd_ctl::ccc_waitq)) 187 _NOTE(MUTEX_PROTECTS_DATA(cmd_ctl::ccc_doneq_mutex, cmd_ctl::ccc_doneq)) 188 189 190 #define GHBA_QHEAD(cccp) ((cccp)->ccc_waitq.Q_qhead) 191 #define GHBA_MAXACTIVE(cccp) ((cccp)->ccc_waitq.Q_maxactive) 192 #define GHBA_NACTIVE(cccp) ((cccp)->ccc_waitq.Q_nactive) 193 194 /* Initialize the HBA's list headers */ 195 #define CCCP_INIT(cccp) { \ 196 L1HEADER_INIT(&(cccp)->ccc_devs); \ 197 L2_INIT(&(cccp)->ccc_doneq); \ 198 } 199 200 201 #define CCCP2GDEVP(cccp) \ 202 (L1_EMPTY(&(cccp)->ccc_devs) \ 203 ? (gdev_t *)NULL \ 204 : (gdev_t *)((cccp)->ccc_devs.l1_headp->le_datap)) 205 206 /* ******************************************************************* */ 207 208 #include "ghd_scsa.h" 209 210 /* 211 * GHD Entry Points 212 */ 213 void ghd_complete(ccc_t *cccp, gcmd_t *cmdp); 214 void ghd_async_complete(ccc_t *cccp, gcmd_t *cmdp); 215 void ghd_doneq_put(ccc_t *cccp, gcmd_t *cmdp); 216 217 int ghd_intr(ccc_t *cccp, void *status, int chno); 218 int ghd_register(char *, ccc_t *, dev_info_t *, int, void *hba_handle, 219 int (*ccc_ccballoc)(gtgt_t *, gcmd_t *, int, int, 220 int, int), 221 void (*ccc_ccbfree)(gcmd_t *), 222 void (*ccc_sg_func)(gcmd_t *, ddi_dma_cookie_t *, 223 int, int), 224 int (*hba_start)(void *, gcmd_t *), 225 void (*hba_complete)(void *, gcmd_t *, int), 226 uint_t (*int_handler)(caddr_t), 227 int (*get_status)(void *, void *, int), 228 void (*process_intr)(void *, void *, int), 229 int (*timeout_func)(void *, gcmd_t *, gtgt_t *, 230 gact_t, int calltype), 231 tmr_t *tmrp, 232 ddi_iblock_cookie_t iblock, 233 int chno); 234 void ghd_unregister(ccc_t *cccp); 235 236 int ghd_transport(ccc_t *cccp, gcmd_t *cmdp, gtgt_t *gtgtp, 237 uint32_t timeout, int polled, void *intr_status); 238 239 int ghd_tran_abort(ccc_t *cccp, gcmd_t *cmdp, gtgt_t *gtgtp, 240 void *intr_status); 241 int ghd_tran_abort_lun(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status); 242 int ghd_tran_reset_target(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status); 243 int ghd_tran_reset_bus(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status); 244 245 246 /* 247 * Allocate a gcmd_t wrapper and HBA private area 248 */ 249 gcmd_t *ghd_gcmd_alloc(gtgt_t *gtgtp, int ccblen, int sleep); 250 251 /* 252 * Free the gcmd_t wrapper and HBA private area 253 */ 254 void ghd_gcmd_free(gcmd_t *gcmdp); 255 256 257 /* 258 * GHD CMD/CCB timer Entry points 259 */ 260 261 int ghd_timer_attach(ccc_t *cccp, tmr_t *tmrp, 262 int (*timeout_func)(void *handle, gcmd_t *, gtgt_t *, 263 gact_t, int)); 264 void ghd_timer_detach(ccc_t *cccp); 265 void ghd_timer_fini(tmr_t *tmrp); 266 void ghd_timer_init(tmr_t *tmrp, clock_t ticks); 267 void ghd_timer_newstate(ccc_t *cccp, gcmd_t *cmdp, gtgt_t *gtgtp, 268 gact_t action, int calltype); 269 void ghd_timer_poll(ccc_t *cccp); 270 void ghd_timer_start(ccc_t *cccp, gcmd_t *cmdp, uint32_t cmd_timeout); 271 void ghd_timer_stop(ccc_t *cccp, gcmd_t *cmdp); 272 273 274 /* 275 * Wait queue utility routines 276 */ 277 278 gtgt_t *ghd_target_init(dev_info_t *, dev_info_t *, ccc_t *, size_t, 279 void *, uint32_t, uint32_t); 280 void ghd_target_free(dev_info_t *, dev_info_t *, ccc_t *, gtgt_t *); 281 void ghd_waitq_shuffle_up(ccc_t *, gdev_t *); 282 void ghd_waitq_delete(ccc_t *, gcmd_t *); 283 int ghd_waitq_process_and_mutex_hold(ccc_t *); 284 void ghd_waitq_process_and_mutex_exit(ccc_t *); 285 286 287 /* 288 * The values for the calltype arg for the ghd_timer_newstate() function 289 */ 290 291 #define GHD_NEWSTATE_TGTREQ 0 292 #define GHD_NEWSTATE_TIMEOUT 1 293 294 /* ******************************************************************* */ 295 296 /* 297 * specify GHD_INLINE to get optimized versions 298 */ 299 #define GHD_INLINE 1 300 #if defined(GHD_DEBUG) || defined(DEBUG) || defined(__lint) 301 #undef GHD_INLINE 302 #endif 303 304 #if defined(GHD_INLINE) 305 #define GHD_COMPLETE(cccp, gcmpd) GHD_COMPLETE_INLINE(cccp, gcmdp) 306 #define GHD_TIMER_STOP(cccp, gcmdp) GHD_TIMER_STOP_INLINE(cccp, gcmdp) 307 #define GHD_DONEQ_PUT(cccp, gcmdp) GHD_DONEQ_PUT_INLINE(cccp, gcmdp) 308 #else 309 #define GHD_COMPLETE(cccp, gcmpd) ghd_complete(cccp, gcmdp) 310 #define GHD_TIMER_STOP(cccp, gcmdp) ghd_timer_stop(cccp, gcmdp) 311 #define GHD_DONEQ_PUT(cccp, gcmdp) ghd_doneq_put(cccp, gcmdp) 312 #endif 313 314 /* 315 * request is complete, stop the request timer and add to doneq 316 */ 317 #define GHD_COMPLETE_INLINE(cccp, gcmdp) \ 318 { \ 319 ghd_waitq_delete(cccp, gcmdp); \ 320 (gcmdp)->cmd_state = GCMD_STATE_DONEQ; \ 321 GHD_TIMER_STOP((cccp), (gcmdp)); \ 322 GHD_DONEQ_PUT((cccp), (gcmdp)); \ 323 } 324 325 #define GHD_TIMER_STOP_INLINE(cccp, gcmdp) \ 326 { \ 327 mutex_enter(&(cccp)->ccc_activel_mutex); \ 328 L2_delete(&(gcmdp)->cmd_timer_link); \ 329 mutex_exit(&(cccp)->ccc_activel_mutex); \ 330 } 331 332 /* 333 * mark the request done and append it to the doneq 334 */ 335 #define GHD_DONEQ_PUT_INLINE(cccp, gcmdp) \ 336 { \ 337 \ 338 mutex_enter(&(cccp)->ccc_doneq_mutex); \ 339 (gcmdp)->cmd_state = GCMD_STATE_DONEQ; \ 340 L2_add(&(cccp)->ccc_doneq, &(gcmdp)->cmd_q, (gcmdp)); \ 341 if (!(cccp)->ccc_hba_pollmode) \ 342 ddi_trigger_softintr((cccp)->ccc_doneq_softid); \ 343 mutex_exit(&(cccp)->ccc_doneq_mutex); \ 344 } 345 346 347 /* ******************************************************************* */ 348 349 /* 350 * These are shortcut macros for linkages setup by GHD 351 */ 352 353 /* 354 * (gcmd_t *) to (struct scsi_pkt *) 355 */ 356 #define GCMDP2PKTP(gcmdp) ((gcmdp)->cmd_pktp) 357 358 /* 359 * (gcmd_t *) to (gtgt_t *) 360 */ 361 #define GCMDP2GTGTP(gcmdp) ((gcmdp)->cmd_gtgtp) 362 363 /* 364 * (struct scsi_pkt *) to (gcmd_t *) 365 */ 366 #define PKTP2GCMDP(pktp) ((gcmd_t *)(pktp)->pkt_ha_private) 367 368 369 /* These are shortcut macros for linkages setup by SCSA */ 370 371 /* 372 * (struct scsi_address *) to (scsi_hba_tran *) 373 */ 374 #define ADDR2TRAN(ap) ((ap)->a_hba_tran) 375 376 /* 377 * (struct scsi_device *) to (scsi_address *) 378 */ 379 #define SDEV2ADDR(sdp) (&(sdp)->sd_address) 380 381 /* 382 * (struct scsi_device *) to (scsi_hba_tran *) 383 */ 384 #define SDEV2TRAN(sdp) ADDR2TRAN(SDEV2ADDR(sdp)) 385 386 /* 387 * (struct scsi_pkt *) to (scsi_hba_tran *) 388 */ 389 #define PKTP2TRAN(pktp) ADDR2TRAN(&(pktp)->pkt_address) 390 391 /* 392 * (scsi_hba_tran_t *) to (per-target-soft-state *) 393 */ 394 #define TRAN2GTGTP(tranp) ((gtgt_t *)((tranp)->tran_tgt_private)) 395 396 /* 397 * (struct scsi_device *) to (per-target-soft-state *) 398 */ 399 #define SDEV2GTGTP(sd) TRAN2GTGTP(SDEV2TRAN(sd)) 400 401 /* 402 * (struct scsi_pkt *) to (per-target-soft-state *) 403 */ 404 #define PKTP2GTGTP(pktp) TRAN2GTGTP(PKTP2TRAN(pktp)) 405 406 407 /* 408 * (scsi_hba_tran_t *) to (per-HBA-soft-state *) 409 */ 410 #define TRAN2HBA(tranp) ((tranp)->tran_hba_private) 411 412 413 /* 414 * (struct scsi_device *) to (per-HBA-soft-state *) 415 */ 416 #define SDEV2HBA(sd) TRAN2HBA(SDEV2TRAN(sd)) 417 418 /* 419 * (struct scsi_address *) to (per-target-soft-state *) 420 */ 421 #define ADDR2GTGTP(ap) TRAN2GTGTP(ADDR2TRAN(ap)) 422 423 /* ******************************************************************* */ 424 425 426 #ifdef __cplusplus 427 } 428 #endif 429 430 #endif /* _GHD_H */ 431