📄 scsi_controller.c
字号:
int function, int reg, unsigned *size, unsigned *flags){ SCSI_CONTROLLER *pscsi = PID2SCSI(node, module); *size = 0; *flags = 0; if (pscsi->contr_spec->pci_map) pscsi->contr_spec->pci_map(pscsi->controller, address, node, module, function, reg, size, flags);}/*===========================================================================*//* Generate host bus transaction. Caller has allocated request structure and *//* filled in address, size, prcr_req_type and completion callbacks. This *//* routine adds source and destination module ID, request type and sends it *//* to the generic I/O module bus interface. *//*===========================================================================*/int SCSI_cntl_host_issue(SCSI_CONTROLLER *pscsi, REQ *req){ req->node = pscsi->nodeid; req->src_proc = pscsi->mid; req->dest_proc = AddrMap_lookup(req->node, req->paddr); req->type = REQUEST; if (req->prcr_req_type == WRITE) { if (((req->paddr % ARCH_linesz2) == 0) && (req->d.mem.count == ARCH_linesz2)) req->type = WRITEPURGE; else req->req_type = READ_OWN; } else { req->req_type = READ_CURRENT; } if (lqueue_full(&(pscsi->dma_queue))) return(0); lqueue_add(&(pscsi->dma_queue), req, pscsi->nodeid); if (IsNotScheduled(pscsi->bus_interface)) schedule_event(pscsi->bus_interface, YS__Simtime + BUS_FREQUENCY); return(1);}/*===========================================================================*//* Generate interrupt transaction. *//* Check PCI configuration space settings, setup interrupt transaction *//* and issue it on system bus. *//*===========================================================================*/int SCSI_cntl_host_interrupt(SCSI_CONTROLLER *pscsi){ REQ *req; int target; unsigned addr; if (lqueue_full(&(pscsi->interrupt_queue))) return(0);#ifdef SCSI_CNTL_TRACE YS__logmsg(pscsi->nodeid, "%.0f: SCSI Controller Interrupt Host\n", YS__Simtime);#endif pscsi->intr_vector = pscsi->pci_me[0].interrupt_line & 0x0F; target = pscsi->pci_me[0].interrupt_line >> 4; req = (REQ *) YS__PoolGetObj(&YS__ReqPool); if (target != 0xFF) /* single-CPU interrupt */ addr = SYSCONTROL_THIS_LOW(target) + SC_INTERRUPT; else addr = SYSCONTROL_LOCAL_LOW + SC_INTERRUPT; req->vaddr = addr; req->paddr = addr; req->size = 4; req->d.mem.buf = (unsigned char*)&(pscsi->intr_vector); req->perform = IO_write_word; req->complete = (void(*)(REQ*, HIT_TYPE))IO_empty_func; req->node = pscsi->nodeid; req->src_proc = pscsi->mid; req->dest_proc = target; req->type = REQUEST; req->req_type = WRITE_UC; req->prcr_req_type = WRITE; req->prefetch = 0; req->ifetch = 0; req->parent = NULL; lqueue_add(&(pscsi->interrupt_queue), req, pscsi->nodeid); if (IsNotScheduled(pscsi->bus_interface)) schedule_event(pscsi->bus_interface, YS__Simtime + BUS_FREQUENCY); return(1);}/*===========================================================================*//* SCSI Controller Host Bus Interface: multiplex reply queue, interrupt *//* queue and DMA queue (in this order/priority) onto generic I/O interface. *//*===========================================================================*/void SCSI_cntl_bus_interface(){ SCSI_CONTROLLER *pscsi = (SCSI_CONTROLLER*)EventGetArg(NULL); LinkQueue *lq; REQ *req; if (!lqueue_empty(&(pscsi->reply_queue))) lq = &(pscsi->reply_queue); else if (!lqueue_empty(&(pscsi->interrupt_queue))) lq = &(pscsi->interrupt_queue); else if (!lqueue_empty(&(pscsi->dma_queue))) lq = &(pscsi->dma_queue); else { YS__warnmsg(pscsi->nodeid, "Spurious bus interface wakeup %i:%i\n", pscsi->nodeid, pscsi->mid); return; } req = lqueue_head(lq); if (IO_start_transaction(PID2IO(pscsi->nodeid, pscsi->mid), req)) {#ifdef SCSI_CNTL_TRACE YS__logmsg(pscsi->nodeid, "[%i] SCSI Issue %s 0x%08X\n", pscsi->mid, ReqName[req->req_type], req->paddr);#endif lqueue_remove(lq); } if ((!lqueue_empty(&(pscsi->reply_queue))) || (!lqueue_empty(&(pscsi->interrupt_queue))) || (!lqueue_empty(&(pscsi->dma_queue)))) schedule_event(pscsi->bus_interface, YS__Simtime + BUS_FREQUENCY);}/*===========================================================================*//* Device won arbitration on SCSI bus. Forward to specific controller. *//*===========================================================================*/void SCSI_cntl_io_wonbus(void *ptr, SCSI_REQ * req){ SCSI_CONTROLLER *pscsi = (SCSI_CONTROLLER*)ptr; if (pscsi->contr_spec->scsi_wonbus) pscsi->contr_spec->scsi_wonbus(pscsi->controller, req);}/*===========================================================================*//* SCSI request arrived for the device - forward to specific controller. *//*===========================================================================*/void SCSI_cntl_io_request(void *ptr, SCSI_REQ * req){ SCSI_CONTROLLER *pscsi = (SCSI_CONTROLLER*)ptr; if (pscsi->contr_spec->scsi_request) pscsi->contr_spec->scsi_request(pscsi->controller, req); }/*===========================================================================*//* SCSI Response arrived for device - forward to specific controller. *//*===========================================================================*/void SCSI_cntl_io_response(void *ptr, SCSI_REQ* req){ SCSI_CONTROLLER *pscsi = (SCSI_CONTROLLER*)ptr; if (pscsi->contr_spec->scsi_response) pscsi->contr_spec->scsi_response(pscsi->controller, req); }/*===========================================================================*//* Print configuration parameters *//* call controller-specific print-routine and then SCSI bus print routine. *//*===========================================================================*/void SCSI_cntl_print_params(int nid, int mid){ SCSI_CONTROLLER *pscsi = PID2SCSI(nid, mid + first_scsi_cntr); PCI_print_config(nid, pscsi->pci_me); if (pscsi->contr_spec->print_params) pscsi->contr_spec->print_params(pscsi->controller); SCSI_bus_print_params(nid);}/*===========================================================================*//* Report statistics: first call controller-specific report routine, then *//* the SCSI bus report routine (which in turn calls the report routines for *//* all attached devices) *//*===========================================================================*/void SCSI_cntl_stat_report(int nid, int mid){ SCSI_CONTROLLER *pscsi = PID2SCSI(nid, mid + first_scsi_cntr); if (pscsi->contr_spec->stat_report) { YS__statmsg(nid, "SCSI Controller %i Statistics\n", mid); pscsi->contr_spec->stat_report(pscsi->controller); } YS__statmsg(nid, "SCSI Bus %i Statistics\n", mid); SCSI_bus_stat_report(pscsi->scsi_bus);}/*===========================================================================*//* Clear statistics: for each node, call controller-specific clear routine *//* and SCSI bus clear routine. *//*===========================================================================*/void SCSI_cntl_stat_clear(int nid, int mid){ SCSI_CONTROLLER *pscsi = PID2SCSI(nid, mid + first_scsi_cntr); if (pscsi->contr_spec->stat_clear) pscsi->contr_spec->stat_clear(pscsi->controller); SCSI_bus_stat_clear(pscsi->scsi_bus);}/*===========================================================================*//* Dump debug information about controller *//*===========================================================================*/void SCSI_cntl_dump(int nid, int mid){ SCSI_CONTROLLER *pscsi = PID2SCSI(nid, mid + first_scsi_cntr); IO_GENERIC *pio = PID2IO(nid, pscsi->mid); REQ *req; YS__logmsg(nid, "\n============== SCSI CONTROLLER %i =============\n", mid); YS__logmsg(nid, "scsi_id(%d), scsi_max_target(%d), scsi_max_lun(%d)\n", pscsi->scsi_id, pscsi->scsi_max_target, pscsi->scsi_max_lun); DumpLinkQueue("reply_queue", &(pscsi->reply_queue), 0x71, Cache_req_dump, nid); DumpLinkQueue("dma_queue", &(pscsi->dma_queue), 0x71, Cache_req_dump, nid); DumpLinkQueue("interrupt_queue", &(pscsi->interrupt_queue), 0x71, Cache_req_dump, nid); YS__logmsg(nid, "bus_interface scheduled: %s\n", IsScheduled(pscsi->bus_interface) ? "yes" : "no"); IO_dump(pio); if (pscsi->contr_spec->dump) pscsi->contr_spec->dump(pscsi->controller); SCSI_bus_dump(pscsi->scsi_bus);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -