650 * Default aac dma attributes
651 */
652 static ddi_dma_attr_t aac_dma_attr = {
653 DMA_ATTR_V0,
654 0, /* lowest usable address */
655 0xffffffffull, /* high DMA address range */
656 0xffffffffull, /* DMA counter register */
657 AAC_DMA_ALIGN, /* DMA address alignment */
658 1, /* DMA burstsizes */
659 1, /* min effective DMA size */
660 0xffffffffull, /* max DMA xfer size */
661 0xffffffffull, /* segment boundary */
662 1, /* s/g list length */
663 AAC_BLK_SIZE, /* granularity of device */
664 0 /* DMA transfer flags */
665 };
666
667 static int aac_tick = AAC_DEFAULT_TICK; /* tick for the internal timer */
668 static uint32_t aac_timebase = 0; /* internal timer in seconds */
669
670 /*
671 * Warlock directives
672 *
673 * Different variables with the same types have to be protected by the
674 * same mutex; otherwise, warlock will complain with "variables don't
675 * seem to be protected consistently". For example,
676 * aac_softstate::{q_wait, q_comp} are type of aac_cmd_queue, and protected
677 * by aac_softstate::{io_lock, q_comp_mutex} respectively. We have to
678 * declare them as protected explictly at aac_cmd_dequeue().
679 */
680 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", scsi_pkt scsi_cdb scsi_status \
681 scsi_arq_status scsi_descr_sense_hdr scsi_information_sense_descr \
682 mode_format mode_geometry mode_header aac_cmd))
683 _NOTE(SCHEME_PROTECTS_DATA("unique per aac_cmd", aac_fib ddi_dma_cookie_t \
684 aac_sge))
685 _NOTE(SCHEME_PROTECTS_DATA("unique per aac_fib", aac_blockread aac_blockwrite \
686 aac_blockread64 aac_raw_io aac_sg_entry aac_sg_entry64 aac_sg_entryraw \
687 aac_sg_table aac_srb))
688 _NOTE(SCHEME_PROTECTS_DATA("unique to sync fib and cdb", scsi_inquiry))
689 _NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address))
690 _NOTE(SCHEME_PROTECTS_DATA("unique to scsi_transport", buf))
691
692 int
693 _init(void)
694 {
695 int rval = 0;
696
697 #ifdef DEBUG
698 mutex_init(&aac_prt_mutex, NULL, MUTEX_DRIVER, NULL);
699 #endif
700 DBCALLED(NULL, 1);
701
702 if ((rval = ddi_soft_state_init((void *)&aac_softstatep,
703 sizeof (struct aac_softstate), 0)) != 0)
704 goto error;
705
706 if ((rval = scsi_hba_init(&aac_modlinkage)) != 0) {
707 ddi_soft_state_fini((void *)&aac_softstatep);
708 goto error;
709 }
710
711 if ((rval = mod_install(&aac_modlinkage)) != 0) {
1055 }
1056
1057 /*
1058 * quiesce(9E) entry point.
1059 *
1060 * This function is called when the system is single-threaded at high
1061 * PIL with preemption disabled. Therefore, this function must not be
1062 * blocked.
1063 *
1064 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
1065 * DDI_FAILURE indicates an error condition and should almost never happen.
1066 */
1067 static int
1068 aac_quiesce(dev_info_t *dip)
1069 {
1070 struct aac_softstate *softs = AAC_DIP2SOFTS(dip);
1071
1072 if (softs == NULL)
1073 return (DDI_FAILURE);
1074
1075 _NOTE(ASSUMING_PROTECTED(softs->state))
1076 AAC_DISABLE_INTR(softs);
1077
1078 return (DDI_SUCCESS);
1079 }
1080
1081 /* ARGSUSED */
1082 static int
1083 aac_getinfo(dev_info_t *self, ddi_info_cmd_t infocmd, void *arg,
1084 void **result)
1085 {
1086 int error = DDI_SUCCESS;
1087
1088 switch (infocmd) {
1089 case DDI_INFO_DEVT2INSTANCE:
1090 *result = (void *)(intptr_t)(MINOR2INST(getminor((dev_t)arg)));
1091 break;
1092 default:
1093 error = DDI_FAILURE;
1094 }
1095 return (error);
1759 DDI_SUCCESS)
1760 rval = AACERR;
1761 } else {
1762 int i;
1763
1764 for (i = 0; i < softs->intr_cnt; i++) {
1765 if (ddi_intr_disable(softs->htable[i]) != DDI_SUCCESS)
1766 rval = AACERR;
1767 }
1768 }
1769 return (rval);
1770 }
1771
1772 /*
1773 * Set pkt_reason and OR in pkt_statistics flag
1774 */
1775 static void
1776 aac_set_pkt_reason(struct aac_softstate *softs, struct aac_cmd *acp,
1777 uchar_t reason, uint_t stat)
1778 {
1779 #ifndef __lock_lint
1780 _NOTE(ARGUNUSED(softs))
1781 #endif
1782 if (acp->pkt->pkt_reason == CMD_CMPLT)
1783 acp->pkt->pkt_reason = reason;
1784 acp->pkt->pkt_statistics |= stat;
1785 }
1786
1787 /*
1788 * Handle a finished pkt of soft SCMD
1789 */
1790 static void
1791 aac_soft_callback(struct aac_softstate *softs, struct aac_cmd *acp)
1792 {
1793 ASSERT(acp->pkt);
1794
1795 acp->flags |= AAC_CMD_CMPLT;
1796
1797 acp->pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | \
1798 STATE_SENT_CMD | STATE_GOT_STATUS;
1799 if (acp->pkt->pkt_state & STATE_XFERRED_DATA)
1800 acp->pkt->pkt_resid = 0;
1801
3130 return (aac_do_sync_io(softs, acp));
3131 else
3132 return (aac_do_poll_io(softs, acp));
3133 }
3134
3135 static void
3136 aac_cmd_initq(struct aac_cmd_queue *q)
3137 {
3138 q->q_head = NULL;
3139 q->q_tail = (struct aac_cmd *)&q->q_head;
3140 }
3141
3142 /*
3143 * Remove a cmd from the head of q
3144 */
3145 static struct aac_cmd *
3146 aac_cmd_dequeue(struct aac_cmd_queue *q)
3147 {
3148 struct aac_cmd *acp;
3149
3150 _NOTE(ASSUMING_PROTECTED(*q))
3151
3152 if ((acp = q->q_head) != NULL) {
3153 if ((q->q_head = acp->next) != NULL)
3154 acp->next = NULL;
3155 else
3156 q->q_tail = (struct aac_cmd *)&q->q_head;
3157 acp->prev = NULL;
3158 }
3159 return (acp);
3160 }
3161
3162 /*
3163 * Add a cmd to the tail of q
3164 */
3165 static void
3166 aac_cmd_enqueue(struct aac_cmd_queue *q, struct aac_cmd *acp)
3167 {
3168 ASSERT(acp->next == NULL);
3169 acp->prev = q->q_tail;
3170 q->q_tail->next = acp;
3171 q->q_tail = acp;
4129
4130 tgt = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4131 DDI_PROP_DONTPASS, "target", -1);
4132 if (tgt == -1)
4133 return (DDI_FAILURE);
4134 lun = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4135 DDI_PROP_DONTPASS, "lun", -1);
4136 if (lun == -1)
4137 return (DDI_FAILURE);
4138
4139 (void) snprintf(name, len, "%x,%x", tgt, lun);
4140 return (DDI_SUCCESS);
4141 }
4142
4143 /*ARGSUSED*/
4144 static int
4145 aac_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
4146 scsi_hba_tran_t *tran, struct scsi_device *sd)
4147 {
4148 struct aac_softstate *softs = AAC_TRAN2SOFTS(tran);
4149 #if defined(DEBUG) || defined(__lock_lint)
4150 int ctl = ddi_get_instance(softs->devinfo_p);
4151 #endif
4152 uint16_t tgt = sd->sd_address.a_target;
4153 uint8_t lun = sd->sd_address.a_lun;
4154 struct aac_device *dvp;
4155
4156 DBCALLED(softs, 2);
4157
4158 if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
4159 /*
4160 * If no persistent node exist, we don't allow .conf node
4161 * to be created.
4162 */
4163 if (aac_find_child(softs, tgt, lun) != NULL) {
4164 if (ndi_merge_node(tgt_dip, aac_name_node) !=
4165 DDI_SUCCESS)
4166 /* Create this .conf node */
4167 return (DDI_SUCCESS);
4168 }
4169 return (DDI_FAILURE);
4212
4213 if (softs->flags & AAC_FLAGS_BRKUP) {
4214 if (ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip,
4215 "buf_break", 1) != DDI_PROP_SUCCESS) {
4216 cmn_err(CE_CONT, "unable to create "
4217 "property for t%dL%d (buf_break)", tgt, lun);
4218 }
4219 }
4220
4221 AACDB_PRINT(softs, CE_NOTE,
4222 "aac_tran_tgt_init: c%dt%dL%d ok (%s)", ctl, tgt, lun,
4223 (dvp->type == AAC_DEV_PD) ? "pd" : "ld");
4224 mutex_exit(&softs->io_lock);
4225 return (DDI_SUCCESS);
4226 }
4227
4228 static void
4229 aac_tran_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
4230 scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
4231 {
4232 #ifndef __lock_lint
4233 _NOTE(ARGUNUSED(hba_dip, tgt_dip, hba_tran))
4234 #endif
4235
4236 struct aac_softstate *softs = SD2AAC(sd);
4237 int tgt = sd->sd_address.a_target;
4238
4239 mutex_enter(&softs->io_lock);
4240 if (tgt < AAC_MAX_LD) {
4241 if (softs->containers[tgt].dev.dip == tgt_dip)
4242 softs->containers[tgt].dev.dip = NULL;
4243 } else {
4244 if (softs->nondasds[AAC_PD(tgt)].dev.dip == tgt_dip)
4245 softs->nondasds[AAC_PD(tgt)].dev.dip = NULL;
4246 softs->nondasds[AAC_PD(tgt)].dev.flags &= ~AAC_DFLAG_VALID;
4247 }
4248 mutex_exit(&softs->io_lock);
4249 }
4250
4251 /*
4252 * Check if the firmware is Up And Running. If it is in the Kernel Panic
4253 * state, (BlinkLED code + 1) is returned.
4254 * 0 -- firmware up and running
5370 if (pkt == NULL) {
5371 int slen;
5372
5373 /* Force auto request sense */
5374 slen = (statuslen > softs->slen) ? statuslen : softs->slen;
5375 pkt = scsi_hba_pkt_alloc(softs->devinfo_p, ap, cmdlen,
5376 slen, tgtlen, sizeof (struct aac_cmd), callback, arg);
5377 if (pkt == NULL) {
5378 AACDB_PRINT(softs, CE_WARN, "Alloc scsi pkt failed");
5379 return (NULL);
5380 }
5381 acp = new_acp = PKT2AC(pkt);
5382 acp->pkt = pkt;
5383 acp->cmdlen = cmdlen;
5384
5385 if (ap->a_target < AAC_MAX_LD) {
5386 acp->dvp = &softs->containers[ap->a_target].dev;
5387 acp->aac_cmd_fib = softs->aac_cmd_fib;
5388 acp->ac_comp = aac_ld_complete;
5389 } else {
5390 _NOTE(ASSUMING_PROTECTED(softs->nondasds))
5391
5392 acp->dvp = &softs->nondasds[AAC_PD(ap->a_target)].dev;
5393 acp->aac_cmd_fib = softs->aac_cmd_fib_scsi;
5394 acp->ac_comp = aac_pd_complete;
5395 }
5396 } else {
5397 acp = PKT2AC(pkt);
5398 new_acp = NULL;
5399 }
5400
5401 if (aac_cmd_dma_alloc(softs, acp, bp, flags, callback, arg) == AACOK)
5402 return (pkt);
5403
5404 if (new_acp)
5405 aac_tran_destroy_pkt(ap, pkt);
5406 return (NULL);
5407 }
5408
5409 /*
5410 * tran_sync_pkt(9E) - explicit DMA synchronization
5411 */
|
650 * Default aac dma attributes
651 */
652 static ddi_dma_attr_t aac_dma_attr = {
653 DMA_ATTR_V0,
654 0, /* lowest usable address */
655 0xffffffffull, /* high DMA address range */
656 0xffffffffull, /* DMA counter register */
657 AAC_DMA_ALIGN, /* DMA address alignment */
658 1, /* DMA burstsizes */
659 1, /* min effective DMA size */
660 0xffffffffull, /* max DMA xfer size */
661 0xffffffffull, /* segment boundary */
662 1, /* s/g list length */
663 AAC_BLK_SIZE, /* granularity of device */
664 0 /* DMA transfer flags */
665 };
666
667 static int aac_tick = AAC_DEFAULT_TICK; /* tick for the internal timer */
668 static uint32_t aac_timebase = 0; /* internal timer in seconds */
669
670 int
671 _init(void)
672 {
673 int rval = 0;
674
675 #ifdef DEBUG
676 mutex_init(&aac_prt_mutex, NULL, MUTEX_DRIVER, NULL);
677 #endif
678 DBCALLED(NULL, 1);
679
680 if ((rval = ddi_soft_state_init((void *)&aac_softstatep,
681 sizeof (struct aac_softstate), 0)) != 0)
682 goto error;
683
684 if ((rval = scsi_hba_init(&aac_modlinkage)) != 0) {
685 ddi_soft_state_fini((void *)&aac_softstatep);
686 goto error;
687 }
688
689 if ((rval = mod_install(&aac_modlinkage)) != 0) {
1033 }
1034
1035 /*
1036 * quiesce(9E) entry point.
1037 *
1038 * This function is called when the system is single-threaded at high
1039 * PIL with preemption disabled. Therefore, this function must not be
1040 * blocked.
1041 *
1042 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
1043 * DDI_FAILURE indicates an error condition and should almost never happen.
1044 */
1045 static int
1046 aac_quiesce(dev_info_t *dip)
1047 {
1048 struct aac_softstate *softs = AAC_DIP2SOFTS(dip);
1049
1050 if (softs == NULL)
1051 return (DDI_FAILURE);
1052
1053 AAC_DISABLE_INTR(softs);
1054
1055 return (DDI_SUCCESS);
1056 }
1057
1058 /* ARGSUSED */
1059 static int
1060 aac_getinfo(dev_info_t *self, ddi_info_cmd_t infocmd, void *arg,
1061 void **result)
1062 {
1063 int error = DDI_SUCCESS;
1064
1065 switch (infocmd) {
1066 case DDI_INFO_DEVT2INSTANCE:
1067 *result = (void *)(intptr_t)(MINOR2INST(getminor((dev_t)arg)));
1068 break;
1069 default:
1070 error = DDI_FAILURE;
1071 }
1072 return (error);
1736 DDI_SUCCESS)
1737 rval = AACERR;
1738 } else {
1739 int i;
1740
1741 for (i = 0; i < softs->intr_cnt; i++) {
1742 if (ddi_intr_disable(softs->htable[i]) != DDI_SUCCESS)
1743 rval = AACERR;
1744 }
1745 }
1746 return (rval);
1747 }
1748
1749 /*
1750 * Set pkt_reason and OR in pkt_statistics flag
1751 */
1752 static void
1753 aac_set_pkt_reason(struct aac_softstate *softs, struct aac_cmd *acp,
1754 uchar_t reason, uint_t stat)
1755 {
1756 _NOTE(ARGUNUSED(softs))
1757 if (acp->pkt->pkt_reason == CMD_CMPLT)
1758 acp->pkt->pkt_reason = reason;
1759 acp->pkt->pkt_statistics |= stat;
1760 }
1761
1762 /*
1763 * Handle a finished pkt of soft SCMD
1764 */
1765 static void
1766 aac_soft_callback(struct aac_softstate *softs, struct aac_cmd *acp)
1767 {
1768 ASSERT(acp->pkt);
1769
1770 acp->flags |= AAC_CMD_CMPLT;
1771
1772 acp->pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | \
1773 STATE_SENT_CMD | STATE_GOT_STATUS;
1774 if (acp->pkt->pkt_state & STATE_XFERRED_DATA)
1775 acp->pkt->pkt_resid = 0;
1776
3105 return (aac_do_sync_io(softs, acp));
3106 else
3107 return (aac_do_poll_io(softs, acp));
3108 }
3109
3110 static void
3111 aac_cmd_initq(struct aac_cmd_queue *q)
3112 {
3113 q->q_head = NULL;
3114 q->q_tail = (struct aac_cmd *)&q->q_head;
3115 }
3116
3117 /*
3118 * Remove a cmd from the head of q
3119 */
3120 static struct aac_cmd *
3121 aac_cmd_dequeue(struct aac_cmd_queue *q)
3122 {
3123 struct aac_cmd *acp;
3124
3125 if ((acp = q->q_head) != NULL) {
3126 if ((q->q_head = acp->next) != NULL)
3127 acp->next = NULL;
3128 else
3129 q->q_tail = (struct aac_cmd *)&q->q_head;
3130 acp->prev = NULL;
3131 }
3132 return (acp);
3133 }
3134
3135 /*
3136 * Add a cmd to the tail of q
3137 */
3138 static void
3139 aac_cmd_enqueue(struct aac_cmd_queue *q, struct aac_cmd *acp)
3140 {
3141 ASSERT(acp->next == NULL);
3142 acp->prev = q->q_tail;
3143 q->q_tail->next = acp;
3144 q->q_tail = acp;
4102
4103 tgt = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4104 DDI_PROP_DONTPASS, "target", -1);
4105 if (tgt == -1)
4106 return (DDI_FAILURE);
4107 lun = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4108 DDI_PROP_DONTPASS, "lun", -1);
4109 if (lun == -1)
4110 return (DDI_FAILURE);
4111
4112 (void) snprintf(name, len, "%x,%x", tgt, lun);
4113 return (DDI_SUCCESS);
4114 }
4115
4116 /*ARGSUSED*/
4117 static int
4118 aac_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
4119 scsi_hba_tran_t *tran, struct scsi_device *sd)
4120 {
4121 struct aac_softstate *softs = AAC_TRAN2SOFTS(tran);
4122 #ifdef DEBUG
4123 int ctl = ddi_get_instance(softs->devinfo_p);
4124 #endif
4125 uint16_t tgt = sd->sd_address.a_target;
4126 uint8_t lun = sd->sd_address.a_lun;
4127 struct aac_device *dvp;
4128
4129 DBCALLED(softs, 2);
4130
4131 if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
4132 /*
4133 * If no persistent node exist, we don't allow .conf node
4134 * to be created.
4135 */
4136 if (aac_find_child(softs, tgt, lun) != NULL) {
4137 if (ndi_merge_node(tgt_dip, aac_name_node) !=
4138 DDI_SUCCESS)
4139 /* Create this .conf node */
4140 return (DDI_SUCCESS);
4141 }
4142 return (DDI_FAILURE);
4185
4186 if (softs->flags & AAC_FLAGS_BRKUP) {
4187 if (ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip,
4188 "buf_break", 1) != DDI_PROP_SUCCESS) {
4189 cmn_err(CE_CONT, "unable to create "
4190 "property for t%dL%d (buf_break)", tgt, lun);
4191 }
4192 }
4193
4194 AACDB_PRINT(softs, CE_NOTE,
4195 "aac_tran_tgt_init: c%dt%dL%d ok (%s)", ctl, tgt, lun,
4196 (dvp->type == AAC_DEV_PD) ? "pd" : "ld");
4197 mutex_exit(&softs->io_lock);
4198 return (DDI_SUCCESS);
4199 }
4200
4201 static void
4202 aac_tran_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
4203 scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
4204 {
4205 _NOTE(ARGUNUSED(hba_dip, tgt_dip, hba_tran))
4206
4207 struct aac_softstate *softs = SD2AAC(sd);
4208 int tgt = sd->sd_address.a_target;
4209
4210 mutex_enter(&softs->io_lock);
4211 if (tgt < AAC_MAX_LD) {
4212 if (softs->containers[tgt].dev.dip == tgt_dip)
4213 softs->containers[tgt].dev.dip = NULL;
4214 } else {
4215 if (softs->nondasds[AAC_PD(tgt)].dev.dip == tgt_dip)
4216 softs->nondasds[AAC_PD(tgt)].dev.dip = NULL;
4217 softs->nondasds[AAC_PD(tgt)].dev.flags &= ~AAC_DFLAG_VALID;
4218 }
4219 mutex_exit(&softs->io_lock);
4220 }
4221
4222 /*
4223 * Check if the firmware is Up And Running. If it is in the Kernel Panic
4224 * state, (BlinkLED code + 1) is returned.
4225 * 0 -- firmware up and running
5341 if (pkt == NULL) {
5342 int slen;
5343
5344 /* Force auto request sense */
5345 slen = (statuslen > softs->slen) ? statuslen : softs->slen;
5346 pkt = scsi_hba_pkt_alloc(softs->devinfo_p, ap, cmdlen,
5347 slen, tgtlen, sizeof (struct aac_cmd), callback, arg);
5348 if (pkt == NULL) {
5349 AACDB_PRINT(softs, CE_WARN, "Alloc scsi pkt failed");
5350 return (NULL);
5351 }
5352 acp = new_acp = PKT2AC(pkt);
5353 acp->pkt = pkt;
5354 acp->cmdlen = cmdlen;
5355
5356 if (ap->a_target < AAC_MAX_LD) {
5357 acp->dvp = &softs->containers[ap->a_target].dev;
5358 acp->aac_cmd_fib = softs->aac_cmd_fib;
5359 acp->ac_comp = aac_ld_complete;
5360 } else {
5361 acp->dvp = &softs->nondasds[AAC_PD(ap->a_target)].dev;
5362 acp->aac_cmd_fib = softs->aac_cmd_fib_scsi;
5363 acp->ac_comp = aac_pd_complete;
5364 }
5365 } else {
5366 acp = PKT2AC(pkt);
5367 new_acp = NULL;
5368 }
5369
5370 if (aac_cmd_dma_alloc(softs, acp, bp, flags, callback, arg) == AACOK)
5371 return (pkt);
5372
5373 if (new_acp)
5374 aac_tran_destroy_pkt(ap, pkt);
5375 return (NULL);
5376 }
5377
5378 /*
5379 * tran_sync_pkt(9E) - explicit DMA synchronization
5380 */
|