in advansys.c [6285:6582]
static void AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
{
EXT_MSG ext_msg;
EXT_MSG out_msg;
ushort halt_q_addr;
bool sdtr_accept;
ushort int_halt_code;
ASC_SCSI_BIT_ID_TYPE scsi_busy;
ASC_SCSI_BIT_ID_TYPE target_id;
PortAddr iop_base;
uchar tag_code;
uchar q_status;
uchar halt_qp;
uchar sdtr_data;
uchar target_ix;
uchar q_cntl, tid_no;
uchar cur_dvc_qng;
uchar asyn_sdtr;
uchar scsi_status;
struct asc_board *boardp;
BUG_ON(!asc_dvc->drv_ptr);
boardp = asc_dvc->drv_ptr;
iop_base = asc_dvc->iop_base;
int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
target_ix = AscReadLramByte(iop_base,
(ushort)(halt_q_addr +
(ushort)ASC_SCSIQ_B_TARGET_IX));
q_cntl = AscReadLramByte(iop_base,
(ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL));
tid_no = ASC_TIX_TO_TID(target_ix);
target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no);
if (asc_dvc->pci_fix_asyn_xfer & target_id) {
asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
} else {
asyn_sdtr = 0;
}
if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
if (asc_dvc->pci_fix_asyn_xfer & target_id) {
AscSetChipSDTR(iop_base, 0, tid_no);
boardp->sdtr_data[tid_no] = 0;
}
AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
return;
} else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
if (asc_dvc->pci_fix_asyn_xfer & target_id) {
AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
boardp->sdtr_data[tid_no] = asyn_sdtr;
}
AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
return;
} else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
AscMemWordCopyPtrFromLram(iop_base,
ASCV_MSGIN_BEG,
(uchar *)&ext_msg,
sizeof(EXT_MSG) >> 1);
if (ext_msg.msg_type == EXTENDED_MESSAGE &&
ext_msg.msg_req == EXTENDED_SDTR &&
ext_msg.msg_len == MS_SDTR_LEN) {
sdtr_accept = true;
if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
sdtr_accept = false;
ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
}
if ((ext_msg.xfer_period <
asc_dvc->sdtr_period_tbl[asc_dvc->min_sdtr_index])
|| (ext_msg.xfer_period >
asc_dvc->sdtr_period_tbl[asc_dvc->
max_sdtr_index])) {
sdtr_accept = false;
ext_msg.xfer_period =
asc_dvc->sdtr_period_tbl[asc_dvc->
min_sdtr_index];
}
if (sdtr_accept) {
sdtr_data =
AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
ext_msg.req_ack_offset);
if (sdtr_data == 0xFF) {
q_cntl |= QC_MSG_OUT;
asc_dvc->init_sdtr &= ~target_id;
asc_dvc->sdtr_done &= ~target_id;
AscSetChipSDTR(iop_base, asyn_sdtr,
tid_no);
boardp->sdtr_data[tid_no] = asyn_sdtr;
}
}
if (ext_msg.req_ack_offset == 0) {
q_cntl &= ~QC_MSG_OUT;
asc_dvc->init_sdtr &= ~target_id;
asc_dvc->sdtr_done &= ~target_id;
AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
} else {
if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
q_cntl &= ~QC_MSG_OUT;
asc_dvc->sdtr_done |= target_id;
asc_dvc->init_sdtr |= target_id;
asc_dvc->pci_fix_asyn_xfer &=
~target_id;
sdtr_data =
AscCalSDTRData(asc_dvc,
ext_msg.xfer_period,
ext_msg.
req_ack_offset);
AscSetChipSDTR(iop_base, sdtr_data,
tid_no);
boardp->sdtr_data[tid_no] = sdtr_data;
} else {
q_cntl |= QC_MSG_OUT;
AscMsgOutSDTR(asc_dvc,
ext_msg.xfer_period,
ext_msg.req_ack_offset);
asc_dvc->pci_fix_asyn_xfer &=
~target_id;
sdtr_data =
AscCalSDTRData(asc_dvc,
ext_msg.xfer_period,
ext_msg.
req_ack_offset);
AscSetChipSDTR(iop_base, sdtr_data,
tid_no);
boardp->sdtr_data[tid_no] = sdtr_data;
asc_dvc->sdtr_done |= target_id;
asc_dvc->init_sdtr |= target_id;
}
}
AscWriteLramByte(iop_base,
(ushort)(halt_q_addr +
(ushort)ASC_SCSIQ_B_CNTL),
q_cntl);
AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
return;
} else if (ext_msg.msg_type == EXTENDED_MESSAGE &&
ext_msg.msg_req == EXTENDED_WDTR &&
ext_msg.msg_len == MS_WDTR_LEN) {
ext_msg.wdtr_width = 0;
AscMemWordCopyPtrToLram(iop_base,
ASCV_MSGOUT_BEG,
(uchar *)&ext_msg,
sizeof(EXT_MSG) >> 1);
q_cntl |= QC_MSG_OUT;
AscWriteLramByte(iop_base,
(ushort)(halt_q_addr +
(ushort)ASC_SCSIQ_B_CNTL),
q_cntl);
AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
return;
} else {
ext_msg.msg_type = MESSAGE_REJECT;
AscMemWordCopyPtrToLram(iop_base,
ASCV_MSGOUT_BEG,
(uchar *)&ext_msg,
sizeof(EXT_MSG) >> 1);
q_cntl |= QC_MSG_OUT;
AscWriteLramByte(iop_base,
(ushort)(halt_q_addr +
(ushort)ASC_SCSIQ_B_CNTL),
q_cntl);
AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
return;
}
} else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
q_cntl |= QC_REQ_SENSE;
if ((asc_dvc->init_sdtr & target_id) != 0) {
asc_dvc->sdtr_done &= ~target_id;
sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
q_cntl |= QC_MSG_OUT;
AscMsgOutSDTR(asc_dvc,
asc_dvc->
sdtr_period_tbl[(sdtr_data >> 4) &
(uchar)(asc_dvc->
max_sdtr_index -
1)],
(uchar)(sdtr_data & (uchar)
ASC_SYN_MAX_OFFSET));
}
AscWriteLramByte(iop_base,
(ushort)(halt_q_addr +
(ushort)ASC_SCSIQ_B_CNTL), q_cntl);
tag_code = AscReadLramByte(iop_base,
(ushort)(halt_q_addr + (ushort)
ASC_SCSIQ_B_TAG_CODE));
tag_code &= 0xDC;
if ((asc_dvc->pci_fix_asyn_xfer & target_id)
&& !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
) {
tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
| ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
}
AscWriteLramByte(iop_base,
(ushort)(halt_q_addr +
(ushort)ASC_SCSIQ_B_TAG_CODE),
tag_code);
q_status = AscReadLramByte(iop_base,
(ushort)(halt_q_addr + (ushort)
ASC_SCSIQ_B_STATUS));
q_status |= (QS_READY | QS_BUSY);
AscWriteLramByte(iop_base,
(ushort)(halt_q_addr +
(ushort)ASC_SCSIQ_B_STATUS),
q_status);
scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B);
scsi_busy &= ~target_id;
AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy);
AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
return;
} else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
AscMemWordCopyPtrFromLram(iop_base,
ASCV_MSGOUT_BEG,
(uchar *)&out_msg,
sizeof(EXT_MSG) >> 1);
if ((out_msg.msg_type == EXTENDED_MESSAGE) &&
(out_msg.msg_len == MS_SDTR_LEN) &&
(out_msg.msg_req == EXTENDED_SDTR)) {
asc_dvc->init_sdtr &= ~target_id;
asc_dvc->sdtr_done &= ~target_id;
AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
boardp->sdtr_data[tid_no] = asyn_sdtr;
}
q_cntl &= ~QC_MSG_OUT;
AscWriteLramByte(iop_base,
(ushort)(halt_q_addr +
(ushort)ASC_SCSIQ_B_CNTL), q_cntl);
AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
return;
} else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
scsi_status = AscReadLramByte(iop_base,
(ushort)((ushort)halt_q_addr +
(ushort)
ASC_SCSIQ_SCSI_STATUS));
cur_dvc_qng =
AscReadLramByte(iop_base,
(ushort)((ushort)ASC_QADR_BEG +
(ushort)target_ix));
if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
scsi_busy = AscReadLramByte(iop_base,
(ushort)ASCV_SCSIBUSY_B);
scsi_busy |= target_id;
AscWriteLramByte(iop_base,
(ushort)ASCV_SCSIBUSY_B, scsi_busy);
asc_dvc->queue_full_or_busy |= target_id;
if (scsi_status == SAM_STAT_TASK_SET_FULL) {
if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
cur_dvc_qng -= 1;
asc_dvc->max_dvc_qng[tid_no] =
cur_dvc_qng;
AscWriteLramByte(iop_base,
(ushort)((ushort)
ASCV_MAX_DVC_QNG_BEG
+ (ushort)
tid_no),
cur_dvc_qng);
/*
* Set the device queue depth to the
* number of active requests when the
* QUEUE FULL condition was encountered.
*/
boardp->queue_full |= target_id;
boardp->queue_full_cnt[tid_no] =
cur_dvc_qng;
}
}
}
AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
return;
}
return;
}