📄 ahc.c
字号:
{ SCSI_REQ *req; int length = 0; if (scb->tcl & SELBUSB) YS__errmsg(ahc->scsi_me->nodeid, "AHC[%i]: Attempt to issue SCSI command on bus B", ahc->scsi_me->mid); req = (SCSI_REQ*)YS__PoolGetObj(&YS__ScsiReqPool); req->initiator = ahc->scsi_id; req->target = scb->tcl >> 4; req->lun = scb->tcl & 0x07; req->parent = NULL; if (scb->control & DISCENB) req->imm_flag = SCSI_FLAG_TRUE; else req->imm_flag = SCSI_FLAG_FALSE; if (scb->control & TAG_ENB) { if ((scb->control & SCB_TAG_TYPE) == 0x00) req->queue_msg = SIMPLE_QUEUE; if ((scb->control & SCB_TAG_TYPE) == 0x01) req->queue_msg = HEAD_OF_QUEUE; if ((scb->control & SCB_TAG_TYPE) == 0x02) req->queue_msg = ORDER_QUEUE; if ((scb->control & SCB_TAG_TYPE) == 0x03) YS__errmsg(ahc->scsi_me->nodeid, "AHC[%i]: Invalid queue type in SCSI command", ahc->scsi_me->mid); } else req->queue_msg = NO_QUEUE; req->queue_tag = scb->tag; /* decode command -------------------------------------------------------*/ switch (scb->command[0]) { case TEST_UNIT_READY: case START_STOP: case PREVENT_ALLOW: req->request_type = SCSI_REQ_MISC; req->length = 0; req->lba = 0; break; case REQUEST_SENSE: req->request_type = SCSI_REQ_REQUEST_SENSE; req->length = scb->command[4]; req->lba = 0; req->aux = 0; scb->write = 1; length = req->length; break; case SCSI_READ_COMMAND: req->request_type = SCSI_REQ_READ; req->length = scb->command[4] > 0 ? scb->command[4]:256; req->lba = ((scb->command[1] & 0x1F) << 16) | (scb->command[2] << 8) | scb->command[3]; scb->write = 1; length = req->length * SCSI_BLOCK_SIZE; break; case SCSI_WRITE_COMMAND: req->request_type = SCSI_REQ_WRITE; req->length = scb->command[4] > 0 ? scb->command[4]:256; req->lba = ((scb->command[1] & 0x1F) << 16) | (scb->command[2] << 8) | scb->command[3]; scb->write = 0; length = req->length * SCSI_BLOCK_SIZE; break; case INQUIRY: req->request_type = SCSI_REQ_INQUIRY; req->length = scb->command[4]; req->lba = 0; scb->write = 1; length = req->length; break; case SCSI_MODE_SENSE: req->request_type = SCSI_REQ_MODE_SENSE; req->length = scb->command[4]; req->lba = 0; req->aux = scb->command[2]; scb->write = 1; length = req->length; break; case READ_CAPACITY: req->request_type = SCSI_REQ_READ_CAPACITY; req->length = 8; req->lba = (scb->command[2] << 24) | (scb->command[3] << 16) | (scb->command[4] << 8) | (scb->command[5]); scb->write = 1; length = req->length; break; case READ_BIG: req->request_type = SCSI_REQ_READ; req->length = (scb->command[7] << 8) | scb->command[8]; req->lba = (scb->command[2] << 24) | (scb->command[3] << 16) | (scb->command[4] << 8) | scb->command[5]; scb->write = 1; length = req->length * SCSI_BLOCK_SIZE; break; case WRITE_BIG: req->request_type = SCSI_REQ_WRITE; req->length = (scb->command[7] << 8) | scb->command[8]; req->lba = (scb->command[2] << 24) | (scb->command[3] << 16) | (scb->command[4] << 8) | scb->command[5]; scb->write = 0; length = req->length * SCSI_BLOCK_SIZE; break; case SCSI_SYNCHRONIZE_CACHE: req->request_type = SCSI_REQ_SYNC_CACHE; req->length = (scb->command[7] << 8) | scb->command[8]; req->lba = (scb->command[2] << 24) | (scb->command[3] << 16) | (scb->command[4] << 8) | scb->command[5]; req->imm_flag = scb->command[1] & 0x02; scb->write = 0; length = 0; break; default: YS__errmsg(ahc->scsi_me->nodeid, "AHC[%i]: Invalid SCSI command 0x%02X", ahc->scsi_me->mid, scb->command[0]); } /* allocate buffer if data length greater then 0 ------------------------*/ if (length > 0) scb->data = malloc(length); else scb->data = NULL; req->buf = (char*)scb->data;#ifdef AHC_TRACE YS__logmsg(ahc->scsi_me->nodeid, "[%i] %.0f: Start SCSI Command %s (0x%02X) Target %i Lun %i Sector %i Size %i\n", ahc->scsi_me->mid, YS__Simtime, SCSI_ReqName[req->request_type], req->request_type, req->target, req->lun, req->lba, req->length);#endif return(SCSI_device_request(ahc->scsi_me->scsi_me, req));}/*=========================================================================*//* SCSI adapter won bus - do nothing right now *//*=========================================================================*/void ahc_scsi_wonbus(void *controller, SCSI_REQ *req){ ahc_t *ahc = (ahc_t*)controller;}/*=========================================================================*//* Request sent to SCSI adapter - not supported *//*=========================================================================*/void ahc_scsi_request(void *controller, SCSI_REQ *req){ ahc_t *ahc = (ahc_t*)controller; YS__errmsg(ahc->scsi_me->nodeid, "AHC[%i]: Request to SCSI controller not supported", ahc->scsi_me->mid);}/*=========================================================================*//* SCSI adapter received response: *//*=========================================================================*/void ahc_scsi_response(void *controller, SCSI_REQ *req){ ahc_t *ahc = (ahc_t*)controller; ahc_scb_t *scb; int n; unsigned char tcl; unsigned char *regs = ahc->regs;#ifdef AHC_TRACE YS__logmsg(ahc->scsi_me->nodeid, "[%i] %.0f AHC: Response %s %i %i (%s)\n", ahc->scsi_me->mid, YS__Simtime, SCSI_RepName[req->reply_type], req->start_block, req->current_data_size, SCSI_ReqName[req->orig_request]);#endif tcl = req->target << 4 | req->lun; scb = NULL; for (n = 0; n < ahc->max_scbs; n++) if (req->queue_msg == NO_QUEUE) { if ((ahc->scbs[n].status != SCB_INACTIVE) && (ahc->scbs[n].tcl == tcl)) { scb = &ahc->scbs[n]; break; } } else { if ((ahc->scbs[n].status != SCB_INACTIVE) && (ahc->scbs[n].tag == req->queue_tag) && (ahc->scbs[n].tcl == tcl)) { scb = &ahc->scbs[n]; break; } } if (scb == NULL) YS__errmsg(ahc->scsi_me->nodeid, "AHC[%i]: SCSI Response to non-existent SCB (%02X)", ahc->scsi_me->mid, tcl); switch (req->reply_type) { case SCSI_REP_COMPLETE: if (IsNotScheduled(ahc->sequencer)) schedule_event(ahc->sequencer, YS__Simtime + ahc->seq_cycle_fast); /* ahc->seq_state = SEQ_RESPONSE; */ /* ahc_shiftin_queue(ahc->reconnect_scbs, scb - ahc->scbs); */ scb->status = SCB_COMPLETE; scb->req = req; break; case SCSI_REP_TIMEOUT: case SCSI_REP_REJECT: scb->status = SCB_ERROR; scb->req = req; break; case SCSI_REP_BUSY: scb->status = SCB_BUSY; scb->req = req; break; case SCSI_REP_CONNECT: if (req->request_type == SCSI_REQ_RECONNECT) {#ifdef AHC_TRACE YS__logmsg(ahc->scsi_me->nodeid, "[%i] %.0f: AHC Reconnect %i %i %i %i\n", ahc->scsi_me->mid, YS__Simtime, IsNotScheduled(ahc->sequencer), ahc->seq_state, ahc->seq_scb, n);#endif if (IsNotScheduled(ahc->sequencer)) { schedule_event(ahc->sequencer, YS__Simtime + ahc->seq_cycle_fast); } if (!((ahc->seq_state == SEQ_DATA) && (ahc->seq_scb == n))) { ahc_queue_shiftin(ahc->reconnect_scbs, n); } } scb->status = SCB_CONNECT; scb->dma_length += req->current_data_size; scb->dma_length_done += req->current_data_size; scb->req = req; if ((req->orig_request == SCSI_REQ_READ) && (req->reply_type == SCSI_REP_CONNECT)) SCSI_bus_perform(ahc->scsi_me->scsi_bus, req); break; case SCSI_REP_SAVE_DATA_POINTER: case SCSI_REP_DISCONNECT: scb->status = SCB_DISCONNECT; scb->req = req; if (req->orig_request == SCSI_REQ_READ) SCSI_bus_perform(ahc->scsi_me->scsi_bus, req); if (req->reply_type == SCSI_REP_DISCONNECT) { YS__PoolReturnObj(&YS__ScsiReqPool, req); scb->req = NULL; } break; default: YS__errmsg(ahc->scsi_me->nodeid, "AHC[%i]: Unknown SCSI response %i", ahc->scsi_me->mid, req->reply_type); }}/*=========================================================================*//* Complete a request: insert it into the output FIFO if successful, *//* interrupt host in any case (if interrupts are enabled) and compute *//* statistics. Free internal buffers and return request to pool. *//* If request was rejected with 'busy' status return it to the head of the *//* input FIFO. *//*=========================================================================*/int ahc_scsi_complete(ahc_t *ahc, ahc_scb_t *scb){ unsigned char *regs = ahc->regs; double lat; if (scb->status == SCB_COMPLETE) { if (!(regs[INTSTAT] & INT_PEND) && (regs[HCNTRL] & INTEN)) { SCSI_cntl_host_interrupt(ahc->scsi_me); ahc->intr_cmpl_count++; ahc->intr_cmpl_start = YS__Simtime; ahc->intr_cmpl_lat_done = 0; ahc->intr_cmpl_clr_done = 0;#ifdef AHC_TRACE YS__logmsg(ahc->scsi_me->nodeid, "[%i] %.0f: Complete Interrupt\n", ahc->scsi_me->mid, YS__Simtime);#endif } regs[INTSTAT] |= CMDCMPLT; ahc_queue_shiftin(ahc->qout_fifo, ahc->seq_scb); regs[QOUTCNT] = ahc_queue_size(ahc->qout_fifo); regs[QOUTFIFO] = ahc_queue_head(ahc->qout_fifo); if (scb->req->orig_request == SCSI_REQ_WRITE) SCSI_bus_perform(ahc->scsi_me->scsi_bus, scb->req); ahc->request_complete_count++; } if (scb->status == SCB_ERROR) { switch (scb->req->reply_type) { case SCSI_REP_TIMEOUT: if (!(regs[INTSTAT] & INT_PEND) && (regs[HCNTRL] & INTEN) && (regs[SIMODE1] & ENSELTIMO)) { SCSI_cntl_host_interrupt(ahc->scsi_me); ahc->intr_scsi_count++; ahc->intr_scsi_start = YS__Simtime; ahc->intr_scsi_lat_done = 0; ahc->intr_scsi_clr_done = 0;#ifdef AHC_TRACE YS__logmsg(ahc->scsi_me->nodeid, "[%i] %.0f: SCSI Interrupt\n", ahc->scsi_me->mid, YS__Simtime);#endif } regs[INTSTAT] |= SCSIINT; regs[SSTAT1] |= SELTO; ahc->seq_pause = 1; break; case SCSI_REP_REJECT: if (!(regs[INTSTAT] & INT_PEND) && (regs[HCNTRL] & INTEN)) { SCSI_cntl_host_interrupt(ahc->scsi_me); ahc->intr_seq_count++; ahc->intr_seq_start = YS__Simtime;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -