📄 si.c
字号:
/* * @(#)si.c 1.1 92/07/30 Copyright (c) 1985 by Sun Microsystems, Inc. *//*#define SIDEBUG /* Allow compiling of debug code */#define REL4 /* Enable release 4 mods */#ifdef REL4#include <sys/types.h>#include <sys/buf.h>#include <sun/dklabel.h>#include <sun/dkio.h>#include <stand/sireg.h>#include <stand/scsi.h>#include <stand/saio.h>#include <mon/sunromvec.h>#include <mon/idprom.h>#else REL4#include "../h/types.h"#include "../h/buf.h"#include "../sun/dklabel.h"#include "../sun/dkio.h"#include "sireg.h"#include "scsi.h"#include "saio.h"#include "../mon/sunromvec.h"#include "../mon/idprom.h"#endif REL4#ifdef SIDEBUG/* Handy debugging 0, 1, and 2 argument printfs */#define DPRINTF(str) \ if (scsi_debug > 1) printf(str)#define DPRINTF1(str, arg1) \ if (scsi_debug > 1) printf(str,arg1)#define DPRINTF2(str, arg1, arg2) \ if (scsi_debug > 1) printf(str,arg1,arg2)/* Handy extended error reporting 0, 1, and 2 argument printfs */#define EPRINTF(str) \ if (scsi_debug) printf(str)#define EPRINTF1(str, arg1) \ if (scsi_debug) printf(str,arg1)#define EPRINTF2(str, arg1, arg2) \ if (scsi_debug) printf(str,arg1,arg2)#else SIDEBUG#define DPRINTF(str)#define DPRINTF1(str, arg2)#define DPRINTF2(str, arg1, arg2)#define EPRINTF(str)#define EPRINTF1(str, arg2)#define EPRINTF2(str, arg1, arg2)#endif SIDEBUG#ifdef BOOTBLOCK#define SC_ERROR(str)#define SC_ERROR1(str, arg1)#else BOOTBLOCK#define SC_ERROR printf#define SC_ERROR1 printf#endif BOOTBLOCK#define SHORT_RESET 0#define LONG_RESET 1/* * Low-level routines common to all devices on the SCSI bus. * * Interface to the routines in this module is via a second "h_sip" * structure contained in the caller's local variables. *//* How si addresses look to the si vme scsi dma hardware */#define SI_VME_DMA_ADDR(x) (((int)x)&0x000FFFFF)/* How si addresses look to the sun3/50 scsi dma hardware */#define SI_OB_DMA_ADDR(x) (((int)x)&0x00FFFFFF)/* How si addresses look to the sun4/110 scsi dma hardware */#define SI_COBRA_DMA_ADDR(x) (((int)x)&0x00FFFFFF)/* * The interfaces we export */extern int scsi_debug;extern char *devalloc();extern char *resalloc();extern int nullsys();extern u_char sc_cdb_size[];int siopen(), sidoit(), si_reset();static u_char junk;#define SI_VME_BASE 0x200000#define SI_OB_BASE 0x140000#define SI_SIZE 0x4000struct sidma { struct udc_table udct; /* dma information for udc */};/* * Open the SCSI host adapter. */intsiopen(h_sip) register struct host_saioreq *h_sip;{ register struct scsi_si_reg *sir; register int ctlr; register int base; register int si_nstd; struct idprom id; enum MAPTYPES space; DPRINTF("siopen:\n"); /* determine type of si interface */ if (idprom(IDFORM_1, &id) == IDFORM_1) { switch (id.id_machine) { case IDM_SUN3_F: case IDM_SUN3_M25: EPRINTF("siopen: CPU SCSI-3\n"); h_sip->ob = 1; base = SI_OB_BASE; space = MAP_OBIO; si_nstd = 1; break; default: EPRINTF("siopen: VME SCSI-3\n"); h_sip->ob = 0; base = SI_VME_BASE; space = MAP_VME24A16D; si_nstd = SC_NSC; break; } } else { EPRINTF("siopen: failed\n"); return (-1); } /* Get base address of registers */ if (h_sip->ctlr <= si_nstd) { ctlr = base + ((int)h_sip->ctlr * SI_SIZE); DPRINTF1("siopen: ctlr= 0x%x\n", (int)ctlr); } else { if ((int)h_sip->devaddr == 0) { EPRINTF("siopen: devalloc failure\n"); return (-2); } else { DPRINTF("siopen: reg. already allocated\n"); return (0); } } /* Map in device registers */ h_sip->devaddr = devalloc(space, (char *)ctlr, sizeof(struct scsi_si_reg)); if ((int)h_sip->devaddr == 0) { EPRINTF("siopen: devalloc failure\n"); return (-2); } sir = (struct scsi_si_reg *)(h_sip->devaddr); /* * If not on-board, peek past 2K bytes to make sure this is * a SCSI-3 host adaptor */#ifndef sun4 if (!h_sip->ob && ((peek((short *)&sir->dma_addr) == -1) || (peek((short *)((int)sir +0x800)) != -1))) { EPRINTF("siopen: peek failed\n"); return (-1); }#else sun4 if (!h_sip->ob && ((peek((short *)&sir->dma_addrl) == -1) || (peek((short *)((int)sir +0x800)) != -1))) { EPRINTF("siopen: peek failed\n"); return (-1); }#endif sun4 /* Allocate dma resources */ h_sip->dmaaddr = 0; if (h_sip->ob == 1) { h_sip->dmaaddr = resalloc(RES_DMAMEM, sizeof(struct sidma)); DPRINTF1("siopen: dmaaddr= 0x%x\n", (int)h_sip->dmaaddr); if (h_sip->dmaaddr == 0) { EPRINTF("siopen: resalloc failure\n"); return (-2); } } /* set host adapter's address modifier bits */ sir->iv_am = VME_SUPV_DATA_24; /* Link top level driver to host adapter */ h_sip->doit = sidoit; h_sip->reset = si_reset; si_reset(h_sip, SHORT_RESET); return (0);}/* * Write a command to the SCSI bus. * * The supplied h_sip is the one opened by scsi_probe. * DMA is done based on h_sip->ma and h_sip->cc. * * Returns -1 for error, otherwise returns the residual count not DMAed * (zero for success). */static intsidoit(cdb, scb, h_sip) struct scsi_cdb *cdb; struct scsi_scb *scb; register struct host_saioreq *h_sip; /* sip for host adapter */{ register struct scsi_si_reg *sir; register u_char *cp; u_char size; register int b; DPRINTF("sidoit:\n"); /* Get to scsi control logic registers */ sir = (struct scsi_si_reg *) h_sip->devaddr; DPRINTF1("sidoit: sir= 0x%x\n", (int)sir); /* Handle SCSI-3 case */ if (si_sbc_wait((caddr_t)&SBC_RD.cbsr, SBC_CBSR_BSY, SCSI_SHORT_DELAY, 0) == 0) { SC_ERROR("si: bus busy\n"); goto FAILED; } /* Select target */ DPRINTF1("sidoit: unit= 0x%x\n", h_sip->unit); SBC_WR.odr = (1 << h_sip->unit) | SI_HOST_ID; SBC_WR.icr = SBC_ICR_DATA; SBC_WR.icr |= SBC_ICR_SEL; /* Wait for target to acknowledge our selection */ if (si_sbc_wait((caddr_t)&SBC_RD.cbsr, SBC_CBSR_BSY, SCSI_SEL_DELAY, 1) == 0) { EPRINTF1("si: device offline, cbsr= 0x%x\n", SBC_RD.cbsr); SBC_WR.icr = 0; return (-2); } SBC_WR.icr = 0; /* Do initial dma setup */ sir->bcr = 0; /* also reset dma_count for vme */ if (h_sip->cc > 0) { if (h_sip->dma_dir == SC_RECV_DATA) { DPRINTF("sidoit: DMA receive\n"); sir->csr &= ~SI_CSR_SEND; } else { DPRINTF("sidoit: DMA send\n"); sir->csr |= SI_CSR_SEND; } sir->csr &= ~SI_CSR_FIFO_RES; sir->csr |= SI_CSR_FIFO_RES; sir->bcr = h_sip->cc; SET_DMA_COUNT(sir, 0); if (h_sip->ob == 0) sir->bcrh = 0; } /* Put command onto scsi bus */ cp = (u_char *)cdb; size = sc_cdb_size[CDB_GROUPID(*cp)]; if (si_putbyte(sir, PHASE_COMMAND, cp, size) == 0) { SC_ERROR("si: cmd put failed\n"); goto FAILED; } if (h_sip->cc > 0) { /* Finish dma setup and wait for dma completion */ if ((int)h_sip->ma & 1) { SC_ERROR("si: illegal odd dma starting address\n"); goto FAILED; } if (h_sip->ob) { si_ob_dma_setup(sir, h_sip); } else { if ((int)h_sip->ma & 0x2) sir->csr |= SI_CSR_BPCON; else sir->csr &= ~SI_CSR_BPCON; SET_DMA_ADDR(sir, SI_VME_DMA_ADDR(h_sip->ma)); SET_DMA_COUNT(sir, h_sip->cc); } si_dma_setup(h_sip, sir); /* No dma, wait for target to request a byte */ } else if (si_sbc_wait((caddr_t)&SBC_RD.cbsr, SBC_CBSR_REQ, SCSI_LONG_DELAY, 1) == 0) { SC_ERROR("si: target never set REQ\n"); goto FAILED; } /* Get status */ junk = SBC_RD.clr; cp = (u_char *)scb; cp[0] = si_getbyte(sir, PHASE_STATUS); b = si_getbyte(sir, PHASE_MSG_IN); if (b != SC_COMMAND_COMPLETE) { EPRINTF("sidoit: no cmd complete msg\n"); /* If b < 0, si_getbyte already printed msg */ if (b >= 0) SC_ERROR("si: invalid message\n"); goto FAILED; } return (h_sip->cc - sir->bcr);FAILED: EPRINTF("sidoit: failed\n"); si_reset(h_sip, LONG_RESET); return (-1);}staticsi_dma_setup(h_sip, sir) register struct host_saioreq *h_sip; register struct scsi_si_reg *sir;{ register char *cp; DPRINTF("si_dma_setup:\n"); /* Setup sbc and start dma */ if (h_sip->dma_dir == SC_RECV_DATA) { DPRINTF("si_dma_setup: RECV\n"); SBC_WR.mr |= SBC_MR_DMA; SBC_WR.tcr = TCR_DATA_IN; SBC_WR.ircv = 0; } else { DPRINTF("si_dma_setup: SEND\n"); SBC_WR.mr |= SBC_MR_DMA; SBC_WR.tcr = TCR_DATA_OUT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -