📄 scsi_disk.c
字号:
pdisk->current_req = NULL; if (IsNotScheduled(pdisk->request_event)) schedule_event(pdisk->request_event, YS__Simtime); } /* schedule sector event for other requests -----------------------------*/ else { pdisk->state = DISK_TRANSFER; if (IsNotScheduled(pdisk->request_event)) schedule_event(pdisk->sector_event, YS__Simtime + rint(DISK_rotation_time(pdisk, 1)*pdisk->ticks_per_ms)); }}/*=========================================================================*//* sector event handler: complete sector has been transferred. *//* Insert data into cache for reads, get new segment unless it is a *//* prefetch. Make segment clean if all data has been written, get new *//* write segment. Schedule new sector or seek event if more data needs to *//* be transferred, or request-event if current request is completed. *//*=========================================================================*/void DISK_sector_handler(){ SCSI_DISK *pdisk = (SCSI_DISK*)EventGetArg(NULL); SCSI_REQ *req = pdisk->current_req, *sreq; int start_block, next_cylinder, next_head, length; if (req == NULL) return; req->current_length++; pdisk->transfer_time += DISK_rotation_time(pdisk, 1); /*=======================================================================*/ /* Handle reads and prefetches (both requested and triggered by a read) */ if ((req->orig_request == SCSI_REQ_READ) || (req->orig_request == SCSI_REQ_PREFETCH)) {#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] Read %.1f Sector %i Segment %i\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id, YS__Simtime, req->start_block + req->current_length - 1, req->cache_segment);#endif pdisk->blocks_read_media++; /* insert sector in cache -------------------------------------------*/ DISK_cache_insert(pdisk, req->start_block + req->current_length - 1, 1, req->cache_segment); /* read-induced prefetch reaches end of segment - abort -------------*/ if ((DISK_cache_segment_full(pdisk, req->cache_segment) || (!lqueue_empty(&(pdisk->inqueue)))) && (req->orig_request == SCSI_REQ_PREFETCH) && (req->request_type == SCSI_REQ_READ)) {#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] Abort Prefetch\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id);#endif pdisk->state = DISK_IDLE; pdisk->current_req = NULL; YS__PoolReturnObj(&YS__ScsiReqPool, req); if (IsNotScheduled(pdisk->request_event)) schedule_event(pdisk->request_event, YS__Simtime); return; } /* requested prefetch or read fills up segment - get new segment ----*/ if ((DISK_cache_segment_full(pdisk, req->cache_segment)) && (req->current_length < req->length)) {#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] Segment full\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id);#endif req->cache_segment = DISK_cache_getsegment(pdisk, req->start_block + req->current_length, req->length - req->current_length - 1, 0); } /* return data if threshold reached ---------------------------------*/ if (((double)(req->current_length - req->transferred) >= (double)(req->length-req->transferred)*pdisk->buffer_full_ratio) && (req->length - req->transferred > 0) && (req->orig_request == SCSI_REQ_READ)) {#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] Return Data %f > %f ?", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id, DISK_estimate_access_time(pdisk, req->start_block+req->current_length, req->length - req->current_length), (double)((req->length - req->transferred) * SCSI_BLOCK_SIZE) / (double)(SCSI_WIDTH * SCSI_FREQUENCY * 1000.0));#endif if (DISK_estimate_access_time(pdisk, req->start_block + req->current_length, req->length - req->current_length) < (double)((req->length - req->transferred) * SCSI_BLOCK_SIZE) / (double)(SCSI_WIDTH * SCSI_FREQUENCY * 1000.0)) { req->request_type = SCSI_REQ_RECONNECT; req->reply_type = SCSI_REP_COMPLETE; req->buscycles = (req->length - req->transferred) * SCSI_BLOCK_SIZE / SCSI_WIDTH; req->current_data_size = req->buscycles * SCSI_WIDTH; req->transferred = req->length; DISK_issue_request(pdisk, req);#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, " %s (%i)\n", SCSI_RepName[req->reply_type], req->buscycles);#endif } else { sreq = (SCSI_REQ*)YS__PoolGetObj(&YS__ScsiReqPool); memcpy(sreq, req, sizeof(SCSI_REQ)); sreq->request_type = SCSI_REQ_RECONNECT; sreq->reply_type = SCSI_REP_SAVE_DATA_POINTER; sreq->buscycles = (req->current_length - req->transferred) * SCSI_BLOCK_SIZE / SCSI_WIDTH; sreq->current_data_size = sreq->buscycles * SCSI_WIDTH; sreq->parent = req; DISK_issue_request(pdisk, sreq); req->transferred = req->current_length;#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, " %s (%i)\n", SCSI_RepName[sreq->reply_type], sreq->buscycles);#endif } } } /*=======================================================================*/ /* handle write request: mark segment as clean if completely written */ if (req->orig_request == SCSI_REQ_WRITE) {#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] Wrote %.1f Sector %i Segment %i\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id, YS__Simtime, req->start_block + req->current_length - 1, req->cache_segment);#endif pdisk->blocks_written_media++; /*-------------------------------------------------------------------*/ /* segment completely written: mark as clean */ if ((req->current_length % ((pdisk->cache_size * 1024) / (pdisk->cache_segments * SCSI_BLOCK_SIZE)) == 0) || (req->current_length == req->length)) { DISK_cache_complete_write(pdisk, req->cache_segment); /*---------------------------------------------------------------*/ /* need to get more data from initiator */ if (req->transferred < req->length) { SCSI_REQ *sreq; length = DISK_cache_write(pdisk, req->start_block + req->transferred, req->length - req->transferred);#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] Get More Data %i %i %i %i\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id, req->length, req->current_length, req->start_block + req->transferred, length);#endif DISK_cache_commit_write(pdisk, req->start_block + req->transferred, req->length - req->transferred); req->buscycles = length * SCSI_BLOCK_SIZE / SCSI_WIDTH; req->current_data_size = req->buscycles * SCSI_WIDTH; req->transferred += length; req->request_type = SCSI_REQ_RECONNECT; if (req->transferred < req->length) req->reply_type = SCSI_REP_SAVE_DATA_POINTER; else req->reply_type = SCSI_REP_COMPLETE; sreq = (SCSI_REQ*)YS__PoolGetObj(&YS__ScsiReqPool); memcpy(sreq, req, sizeof(SCSI_REQ)); DISK_issue_request(pdisk, sreq); } if ((pdisk->fast_writes) && (req->imm_flag) && (req->request_type != SCSI_REQ_RECONNECT)) { req->start_block = 0; req->length = MAXINT; req->cache_segment = DISK_cache_getwsegment(pdisk, &(req->start_block), &(req->length));#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] New Segment Fast %i\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id, req->cache_segment);#endif if (req->cache_segment < 0) { pdisk->state = DISK_IDLE; pdisk->current_req = NULL; YS__PoolReturnObj(&YS__ScsiReqPool, req); if (IsNotScheduled(pdisk->request_event)) schedule_event(pdisk->request_event, YS__Simtime); return; } req->current_length = 0; req->transferred = req->length; req->lba = req->start_block; } else if (req->current_length < req->length) { req->cache_segment = DISK_cache_getsegment(pdisk, req->start_block + req->current_length, 1, 1);#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] New Segment %i %i -> %i\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id, req->start_block + req->current_length, req->length - req->current_length, req->cache_segment);#endif } } } /*=======================================================================*/ /* handle sync request: mark segment as clean if completely written */ if (req->orig_request == SCSI_REQ_SYNC_CACHE) {#ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] Synced %.1f Sector %i Segment %i\n", pdisk->scsi_me->scsi_bus->bus_id+1, pdisk->scsi_me->dev_id, YS__Simtime, req->start_block + req->current_length - 1, req->cache_segment);#endif pdisk->blocks_written_media++; if (req->current_length == req->length) { DISK_cache_complete_write(pdisk, req->cache_segment); req->start_block = 0; /* not exactly correct @@@ */ req->length = MAXINT; req->cache_segment = DISK_cache_getwsegment(pdisk, &(req->start_block), &(req->length)); req->current_length = 0; if (req->cache_segment < 0) { if (!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+pdisk->cntl_overhead*SCSI_FREQ_RATIO); return; } } } /*=======================================================================*/ /* transfer next sector: wait for rotation if on same track, or seek */ if (req->current_length < req->length) { next_cylinder = DISK_sector_to_cylinder(pdisk, req->start_block + req->current_length); next_head = DISK_sector_to_head(pdisk, req->start_block + req->current_length); if ((next_cylinder == pdisk->current_cylinder) && (next_head == pdisk->current_head) && ((req->start_block + req->current_length == DISK_sector_at_time(pdisk, next_head, next_cylinder, YS__Simtime)) || (req->start_block + req->current_length + 1 == DISK_sector_at_time(pdisk, next_head, next_cylinder, YS__Simtime)))) { if (IsNotScheduled(pdisk->sector_event)) schedule_event(pdisk->sector_event, YS__Simtime + floor(DISK_rotation_time(pdisk, 1) * pdisk->ticks_per_ms)); pdisk->seek_target_sector = req->start_block + req->current_length; #ifdef SCSI_DISK_TRACE YS__logmsg(pdisk->scsi_me->scsi_bus->node_id, "[%i:%i] More Transfer %i %i (estimated %f ms %f) -> %.0f\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -