📄 scsi_disk.c
字号:
pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id, req->current_length, req->length, DISK_estimate_access_time(pdisk, req->start_block+req->current_length, req->length - req->current_length), DISK_estimate_access_time(pdisk, req->start_block+req->current_length, req->length - req->current_length) * pdisk->ticks_per_ms, YS__Simtime + rint(DISK_rotation_time(pdisk, 1) * pdisk->ticks_per_ms));#endif } else { DISK_do_seek(pdisk, req->start_block + req->current_length, req->orig_request == SCSI_REQ_WRITE);#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] More Seek\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id);#endif } } /* all blocks transferred -----------------------------------------------*/ else { /* prefetch is complete ---------------------------------------------*/ if ((req->orig_request == SCSI_REQ_PREFETCH) || (req->request_type == SCSI_REQ_PREFETCH)) {#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] %.0f: DISK Prefetch %s %s %i\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id, YS__Simtime, SCSI_ReqName[req->request_type], SCSI_ReqName[req->orig_request], req->imm_flag);#endif if ((req->orig_request == SCSI_REQ_PREFETCH) && (!req->imm_flag)) { req->request_type = SCSI_REQ_RECONNECT; req->reply_type = SCSI_REP_COMPLETE; req->buscycles = 0; req->current_data_size = 0; DISK_issue_request(pdisk, req); } else YS__PoolReturnObj(&YS__ScsiReqPool, req); pdisk->current_req = NULL; pdisk->state = DISK_IDLE; if (IsNotScheduled(pdisk->request_event)) schedule_event(pdisk->request_event, YS__Simtime); } /* read complete: start prefetch if queue is empty ------------------*/ if ((req->orig_request == SCSI_REQ_READ) && (req->request_type != SCSI_REQ_PREFETCH)) if ((lqueue_empty(&(pdisk->inqueue))) && (!DISK_cache_segment_full(pdisk, req->cache_segment)) && (pdisk->prefetch)) { sreq = (SCSI_REQ*)YS__PoolGetObj(&YS__ScsiReqPool); memcpy(sreq, req, sizeof(SCSI_REQ)); sreq->orig_request = SCSI_REQ_PREFETCH; sreq->request_type = SCSI_REQ_READ; sreq->start_block = req->start_block + req->length; sreq->length = req->length; /* configure length @@ */ sreq->imm_flag = 1;#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] Start Prefetch %p %i\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id, sreq, sreq->start_block);#endif pdisk->current_req = sreq; pdisk->state = DISK_IDLE; } else { pdisk->state = DISK_IDLE; pdisk->current_req = NULL; } /* write complete: issue response if not fast-write -----------------*/ if (req->orig_request == SCSI_REQ_WRITE) { if ((!pdisk->fast_writes) || (!req->imm_flag)) { req->request_type = SCSI_REQ_RECONNECT; req->reply_type = SCSI_REP_COMPLETE; req->buscycles = 0; req->current_data_size = 0; DISK_issue_request(pdisk, req); } pdisk->state = DISK_IDLE; pdisk->current_req = NULL; }#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] Done\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id);#endif if (IsNotScheduled(pdisk->request_event)) schedule_event(pdisk->request_event, YS__Simtime); }}/*=========================================================================*//* Issue a SCSI reply transaction on the bus. Arbitrate for bus if output *//* queue is empty, otherwise just put it in the queue. *//*=========================================================================*/int DISK_issue_request(SCSI_DISK *pdisk, SCSI_REQ* req){ if (lqueue_full(&(pdisk->outqueue))) return(0); if (lqueue_empty(&(pdisk->outqueue))) { if (SCSI_device_request(pdisk->scsi_me, req) == 1) return(1); } lqueue_add(&(pdisk->outqueue), req, pdisk->scsi_me->scsi_bus->node_id); return(1);}/*=========================================================================*//* Callback function for when the disk wins the bus. Arbitrate again if *//* more requests are pending in the outqueue. *//*=========================================================================*/void DISK_wonbus(void *ptr, SCSI_REQ *req){ SCSI_DISK *pdisk = (SCSI_DISK*)ptr; SCSI_REQ *next_req; if (!lqueue_empty(&(pdisk->outqueue))) { lqueue_get(&(pdisk->outqueue), next_req); SCSI_device_request(pdisk->scsi_me, next_req); }}/*=========================================================================*//* Callback function for when the disk receives a request. Check validity. *//* Reject if invalid block number, or non-queue request and queue is full. *//* Enqueue reads and disconnect. Enqueue writes, transfer data until write *//* segments are full and return disconnect, save_data_ptr, busy or *//* complete. Enqueue other requests. Fill in return data structure for *//* inquiry and read_capacity requests. *//* Schedule request-event if disk is idle and event is not yet scheduled. *//*=========================================================================*/void DISK_request(void *ptr, SCSI_REQ *req){ SCSI_DISK *pdisk = (SCSI_DISK*)ptr; SCSI_REQ *sreq; int rc; req->orig_request = req->request_type; req->start_block = req->lba; req->transferred = 0; req->buscycles = pdisk->cntl_overhead;#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] DISK %.1f Request %s Block %i Length %i\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id, YS__Simtime, SCSI_ReqName[req->request_type], req->start_block, req->length);#endif /*-----------------------------------------------------------------------*/ /* check block number and length */ if ((req->request_type == SCSI_REQ_READ) || (req->request_type == SCSI_REQ_WRITE) || (req->request_type == SCSI_REQ_PREFETCH) || (req->request_type == SCSI_REQ_SEEK)) { if ((req->start_block < 0) || (req->start_block >= pdisk->cylinders*pdisk->heads*pdisk->sectors) || (req->start_block + req->length < 0) || (req->start_block + req->length > pdisk->cylinders*pdisk->heads*pdisk->sectors)) { req->reply_type = SCSI_REP_REJECT; pdisk->sense_data[req->initiator].error = 0x70; pdisk->sense_data[req->initiator].segment = 0; pdisk->sense_data[req->initiator].key = SCSI_SENSE_ILLEGAL_REQUEST; pdisk->sense_data[req->initiator].info0 = 0; pdisk->sense_data[req->initiator].info1 = 0; pdisk->sense_data[req->initiator].info2 = 0; pdisk->sense_data[req->initiator].info3 = 0; pdisk->sense_data[req->initiator].add_length = 0; return; } } if ((req->request_type != SCSI_REQ_INQUIRY) && (req->request_type != SCSI_REQ_MISC) && (req->lun != 0)) { req->reply_type = SCSI_REP_REJECT; pdisk->sense_data[req->initiator].error = 0x70; pdisk->sense_data[req->initiator].segment = 0; pdisk->sense_data[req->initiator].key = SCSI_SENSE_ILLEGAL_REQUEST; pdisk->sense_data[req->initiator].info0 = 0; pdisk->sense_data[req->initiator].info1 = 0; pdisk->sense_data[req->initiator].info2 = 0; pdisk->sense_data[req->initiator].info3 = 0; pdisk->sense_data[req->initiator].add_length = 0; return; } if (req->request_type != SCSI_REQ_REQUEST_SENSE) { pdisk->sense_data[req->initiator].error = 0x70; pdisk->sense_data[req->initiator].segment = 0; pdisk->sense_data[req->initiator].key = SCSI_SENSE_NONE; pdisk->sense_data[req->initiator].info0 = 0; pdisk->sense_data[req->initiator].info1 = 0; pdisk->sense_data[req->initiator].info2 = 0; pdisk->sense_data[req->initiator].info3 = 0; pdisk->sense_data[req->initiator].add_length = 0; } /*-----------------------------------------------------------------------*/ /* simple (non-queue) request and queue is not empty - reject */ if ((req->queue_msg == NO_QUEUE) && ((!lqueue_empty(&(pdisk->inqueue))) || (pdisk->current_req != NULL))) { if ((pdisk->current_req != NULL) && (((pdisk->current_req->orig_request == SCSI_REQ_PREFETCH) && (pdisk->current_req->request_type == SCSI_REQ_READ)) || ((pdisk->current_req->orig_request == SCSI_REQ_WRITE) && (pdisk->current_req->imm_flag) && (pdisk->fast_writes)))) { if (!((pdisk->current_req->orig_request == SCSI_REQ_WRITE) && ((req->request_type == SCSI_REQ_SYNC_CACHE) || (req->request_type == SCSI_REQ_WRITE)))) {#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] Abort Current Request %s\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id, SCSI_ReqName[pdisk->current_req->orig_request]);#endif YS__PoolReturnObj(&YS__ScsiReqPool, pdisk->current_req); pdisk->current_req = NULL; pdisk->state = DISK_IDLE; } } else {#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] Queue not empty\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id); if (pdisk->current_req != NULL) YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] Current: %s %s %i %p\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id, SCSI_ReqName[pdisk->current_req->request_type], SCSI_ReqName[pdisk->current_req->orig_request], pdisk->current_req->start_block, pdisk->current_req); else YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] Size: %i\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id, pdisk->inqueue.size);#endif req->reply_type = SCSI_REP_BUSY; return; } } /*-----------------------------------------------------------------------*/ /* queue request and queue is full - reject */ if ((req->queue_msg != NO_QUEUE) && (lqueue_full(&(pdisk->inqueue)))) {#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] Queue full\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id);#endif req->reply_type = SCSI_REP_BUSY; return; } /*-----------------------------------------------------------------------*/ /* read request: disconnect, put in queue and schedule handler */ if (req->request_type == SCSI_REQ_READ) { sreq = (SCSI_REQ*)YS__PoolGetObj(&YS__ScsiReqPool); memcpy(sreq, req, sizeof(SCSI_REQ)); if (sreq->queue_msg == HEAD_OF_QUEUE) { lqueue_add_head(&(pdisk->inqueue), sreq, pdisk->scsi_me->scsi_bus->node_id); } else { lqueue_add(&(pdisk->inqueue), sreq, pdisk->scsi_me->scsi_bus->node_id); } if (IsNotScheduled(pdisk->request_event)) schedule_event(pdisk->request_event, YS__Simtime + 0 ); /* pdisk->cntl_overhead * SCSI_FREQ_RATIO); */ req->reply_type = SCSI_REP_DISCONNECT; pdisk->requests_read++; pdisk->blocks_read += req->length; return; } /*-----------------------------------------------------------------------*/ /* write request: disconnect, put in cache and in queue, schedule handler*/ if (req->request_type == SCSI_REQ_WRITE) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -