📄 si.c
字号:
SBC_WR.icr = SBC_ICR_DATA; SBC_WR.send = 0; } if (h_sip->ob == 0) { sir->csr |= SI_CSR_DMA_EN; } /* Wait for dma completion */ if (si_wait(&sir->csr, SI_CSR_SBC_IP | SI_CSR_DMA_IP | SI_CSR_DMA_CONFLICT, 1) == 0) { SC_ERROR("si: dma never completed\n"); si_dma_cleanup(sir, h_sip); goto FAILED; } /* Check reason for dma completion */ if (sir->csr & SI_CSR_SBC_IP) { /* Dma operation should done now. */ si_dma_cleanup(sir, h_sip); } else { DPRINTF("sidoit: ha error exit\n"); if (sir->csr & SI_CSR_DMA_CONFLICT) { SC_ERROR("si: invalid reg access during dma\n"); } else if (sir->csr & SI_CSR_DMA_BUS_ERR) { SC_ERROR("si: bus error during dma\n"); } else { SC_ERROR("si: dma overrun\n"); } si_dma_cleanup(sir, h_sip); goto FAILED; } /* Handle special dma recv situations */ if (h_sip->dma_dir == SC_RECV_DATA) { if (h_sip->ob) { sir->udc_raddr = UDC_ADR_COUNT; if (si_wait(&sir->csr, SI_CSR_FIFO_EMPTY, 1) == 0) { SC_ERROR("si: fifo never emptied\n"); si_dma_cleanup(sir, h_sip); goto FAILED; } /* If odd byte recv, must grab last byte by hand */ if ((h_sip->cc - sir->bcr) & 1) { DPRINTF("si_dma_setup: lob 1\n"); cp = h_sip->ma + (h_sip->cc - sir->bcr) - 1; *cp = (sir->fifo_data & 0xff00) >> 8; /* Udc may not dma last word */ } else if (((sir->udc_rdata *2) - sir->bcr) == 2) { DPRINTF("si_dma_setup: lob 2\n"); cp = h_sip->ma + (h_sip->cc - sir->bcr); *(cp - 2) = (sir->fifo_data & 0xff00) >> 8; *(cp - 1) = sir->fifo_data & 0x00ff; } } else if ((sir->csr & SI_CSR_LOB) != 0) { cp = h_sip->ma + (h_sip->cc - sir->bcr); if ((sir->csr & SI_CSR_BPCON) == 0) { switch (sir->csr & SI_CSR_LOB) { case SI_CSR_LOB_THREE: DPRINTF("si_dma_setup: lob 3\n"); *(cp - 3) = (sir->bprh & 0xff00) >> 8; *(cp - 2) = (sir->bprh & 0x00ff); *(cp - 1) = (sir->bprl & 0xff00) >> 8; break; case SI_CSR_LOB_TWO: DPRINTF("si_dma_setup: lob 2\n"); *(cp - 2) = (sir->bprh & 0xff00) >> 8; *(cp - 1) = (sir->bprh & 0x00ff); break; case SI_CSR_LOB_ONE: DPRINTF("si_dma_setup: lob 1\n"); *(cp - 1) = (sir->bprh & 0xff00) >> 8; break; } } else { *(cp - 1) = (sir->bprl & 0xff00) >> 8; } } } /* Clear sbc interrupt */FAILED: junk = SBC_RD.clr; return;}static intsi_ob_dma_setup(sir, h_sip) register struct scsi_si_reg *sir; register struct host_saioreq *h_sip;{ register struct udc_table *udct; register int dmaaddr; udct = (struct udc_table *)(h_sip->dmaaddr); DPRINTF("si_ob_setup:\n"); /* Setup udc dma info */ dmaaddr = SI_OB_DMA_ADDR(h_sip->ma); udct->haddr = ((dmaaddr & 0xff0000) >> 8) | UDC_ADDR_INFO; udct->laddr = dmaaddr & 0xffff; udct->hcmr = UDC_CMR_HIGH; udct->count = h_sip->cc / 2; if (h_sip->dma_dir == SC_RECV_DATA) { DPRINTF("si_ob_setup: DMA receive\n"); udct->rsel = UDC_RSEL_RECV; udct->lcmr = UDC_CMR_LRECV; } else { DPRINTF("si_ob_setup: DMA send\n"); udct->rsel = UDC_RSEL_SEND; udct->lcmr = UDC_CMR_LSEND; if (h_sip->cc & 1) { udct->count++; } } /* Initialize chain address register */ DELAY(SI_UDC_WAIT); sir->udc_raddr = UDC_ADR_CAR_HIGH; DELAY(SI_UDC_WAIT); sir->udc_rdata = ((int)udct & 0xff0000) >> 8; DELAY(SI_UDC_WAIT); sir->udc_raddr = UDC_ADR_CAR_LOW; DELAY(SI_UDC_WAIT); sir->udc_rdata = (int)udct & 0xffff; /* Initialize master mode register */ DELAY(SI_UDC_WAIT); sir->udc_raddr = UDC_ADR_MODE; DELAY(SI_UDC_WAIT); sir->udc_rdata = UDC_MODE; /* Issue start chain command */ DELAY(SI_UDC_WAIT); sir->udc_raddr = UDC_ADR_COMMAND; DELAY(SI_UDC_WAIT); sir->udc_rdata = UDC_CMD_STRT_CHN;}/* * Reset some register information after a dma operation. */static intsi_dma_cleanup(sir, h_sip) register struct scsi_si_reg *sir; register struct host_saioreq *h_sip;{ DPRINTF("si_dma_cleanup:\n"); if (h_sip->ob) { sir->udc_raddr = UDC_ADR_COMMAND; DELAY(SI_UDC_WAIT); sir->udc_rdata = UDC_CMD_RESET; } else { sir->csr &= ~SI_CSR_DMA_EN; SET_DMA_ADDR(sir, 0); } SBC_WR.mr &= ~SBC_MR_DMA; SBC_WR.icr = 0; SBC_WR.tcr = TCR_UNSPECIFIED;}/* * Wait for a condition to be (de)asserted. */static intsi_wait(reg, cond, set) register u_short *reg; register u_short cond; register int set;{ int i; register u_short regval; /* DPRINTF("si_wait:\n"); */ for (i = 0; i < SCSI_LONG_DELAY; i++) { regval = *reg; if ((set == 1) && (regval & cond)) { return (1); } if ((set == 0) && !(regval & cond)) { return (1); } DELAY(10); } return (0);}/* * Wait for a condition to be (de)asserted on the scsi bus. */static intsi_sbc_wait(reg, cond, delay, set) register caddr_t reg; register u_char cond; register int set; int delay;{ register u_char regval; int i; /* DPRINTF("si_sbc_wait:\n"); */ for (i = 0; i < delay; i++) { regval = *reg; if ((set == 1) && (regval & cond)) { return (1); } if ((set == 0) && !(regval & cond)) { return (1); } DELAY(10); } return (0);}/* * Put a byte onto the scsi bus. */static intsi_putbyte(sir, phase, data, num) register struct scsi_si_reg *sir; register u_short phase; register u_char *data; register u_char num;{ register int i; register u_char icr; DPRINTF("si_putbyte:\n"); /* Set up tcr so a phase match will occur */ sir->sbc_wreg.tcr = phase >> 2; icr = SBC_WR.icr; /* Put all desired bytes onto scsi bus */ for (i = 0; i < num; i++) { SBC_WR.icr = icr | SBC_ICR_DATA; /* clear ack */ /* Wait for target to request a byte */ if (si_sbc_wait((caddr_t)&SBC_RD.cbsr, SBC_CBSR_REQ, SCSI_SHORT_DELAY, 1) == 0) { SC_ERROR1("si: REQ not active, cbsr 0x%x\n", SBC_RD.cbsr); return (0); } /* Load data for transfer */ SBC_WR.odr = *data++; /* Complete req/ack handshake */ SBC_WR.icr |= SBC_ICR_ACK; if (si_sbc_wait((caddr_t)&SBC_RD.cbsr, SBC_CBSR_REQ, SCSI_SHORT_DELAY, 0) == 0) { SC_ERROR("si: target never released REQ\n"); return (0); } } SBC_WR.tcr = 0; SBC_WR.icr = 0; return (1);}/* * Get a byte from the scsi bus. */static intsi_getbyte(sir, phase) register struct scsi_si_reg *sir; u_short phase;{ u_char data; DPRINTF("si_getbyte:\n"); /* Wait for target request */ if (si_sbc_wait((caddr_t)&SBC_RD.cbsr, SBC_CBSR_REQ, SCSI_SHORT_DELAY, 1) == 0) { SC_ERROR1("si: REQ not active, cbsr 0x%x\n", SBC_RD.cbsr); goto FAILED; } /* Check for correct phase on scsi bus */ if (phase != (SBC_RD.cbsr & CBSR_PHASE_BITS)) { SC_ERROR1("si: wrong phase, cbsr 0x%x\n", SBC_RD.cbsr); goto FAILED; } /* Grab data */ data = SBC_RD.cdr; SBC_WR.icr = SBC_ICR_ACK; /* Complete req/ack handshake */ if (si_sbc_wait((caddr_t)&SBC_RD.cbsr, SBC_CBSR_REQ, SCSI_SHORT_DELAY, 0) == 0) { SC_ERROR("si: target never released REQ\n"); goto FAILED; } SBC_WR.tcr = 0; SBC_WR.icr = 0; /* Clear ack */ return (data);FAILED: SBC_WR.tcr = 0; SBC_WR.icr = 0; /* Clear ack */ return (-1);}/* * Reset SCSI control logic. */static intsi_reset(h_sip, flag) register struct host_saioreq *h_sip; int flag;{ register struct scsi_si_reg *sir; DPRINTF("si_reset:\n"); sir = (struct scsi_si_reg *) h_sip->devaddr; /* Reset bcr, fifo, udc, and sbc */ sir->csr = 0; DELAY(10); sir->bcr = 0; sir->csr = SI_CSR_SCSI_RES | SI_CSR_FIFO_RES; if(h_sip->ob == 0) { SET_DMA_ADDR(sir, 0); SET_DMA_COUNT(sir, 0); } /* Issue scsi bus reset */ if (flag != SHORT_RESET) { SBC_WR.icr = SBC_ICR_RST; DELAY(100); SBC_WR.icr = 0; SBC_WR.tcr = 0; SBC_WR.mr = 0; junk = SBC_RD.clr; DELAY(SCSI_RESET_DELAY); /* Recovery time */ }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -