📄 sm.c
字号:
/* * @(#)sm.c 1.1 92/07/30 Copyright (c) 1988 by Sun Microsystems, Inc. * * Emulex ESP SCSI (low-level) driver * * * 3/89 KSAM Send back exact amount of transferred bytes for * Front-load 1/2 tape per 4.0.3 FCS release. * 11/88 KSAM Add in support for 4.0.3 beta release * 9/88 KSAM Change to match the new 4.0 REV-2 SCSI structure * 8/88 KSAM Add in Stingray support * 5/88 KSAM initial written */#if (defined sun4) || (defined sun3x)#define REL4 /* enable release 4.00 mods */#ifdef notdef#define SMEPRINT /* Allow error printfs */#define SMDEBUG /* Allow compiling of debug code */#endif notdef#ifdef REL4#include <sys/types.h>#include <sys/buf.h>#include <sun/dklabel.h>#include <sun/dkio.h>#include <stand/smreg.h>#include <stand/scsi.h>#include <stand/saio.h>#else REL4#include "../h/types.h"#include "../h/buf.h"#include "../sun/dklabel.h"#include "../sun/dkio.h"#include "smreg.h"#include "scsi.h"#include "saio.h"#endif REL4#ifdef REL4#include <mon/sunromvec.h>#include <mon/idprom.h>#else REL4#include "../mon/sunromvec.h"#include "../mon/idprom.h"#endif REL4/* for bring-up stage, print all error messages */#ifdef SMDEBUGint sm_debug = 1; /* normally enable error-printfs *//* Handy debugging 0, 1, and 2 argument printfs, NEED "sm_debug" */#define DPRINTF(str) \ if (sm_debug > 2) printf(str)#define DPRINTF1(str, arg1) \ if (sm_debug > 3) printf(str,arg1)#define DPRINTF2(str, arg1, arg2) \ if (sm_debug > 4) printf(str,arg1,arg2)#define DEBUG_DELAY(cnt) \ if (sm_debug > 5) DELAY(cnt)#define EPRINTF(str) \ if (sm_debug) printf(str)#define EPRINTF1(str, arg1) \ if (sm_debug) printf(str,arg1)#define EPRINTF2(str, arg1, arg2) \ if (sm_debug) printf(str,arg1,arg2)#else SMDEBUG#define DEBUG_DELAY(cnt)#define DPRINTF(str) #define DPRINTF1(str, arg1) #define DPRINTF2(str, arg1, arg2) #ifdef SMEPRINT#define EPRINTF(str) printf(str)#define EPRINTF1(str, arg1) printf(str,arg1)#define EPRINTF2(str, arg1, arg2) printf(str,arg1,arg2)#else#define EPRINTF(str)#define EPRINTF1(str, arg1) #define EPRINTF2(str, arg1, arg2) #endif SMEPRINT#endif SMDEBUG/* * 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. * * This "h_sip" must be initialized with h_sip->smboottab = sm_driver * and must then be devopen()ed before any I/O can be done. * * The device must be closed with devclose(). *//* * The interfaces we export */extern int scsi_debug;extern char *devalloc();extern char *resalloc();extern int nullsys();extern u_char sc_cdb_size[];int smopen(), smdoit(), sm_reset();/* special snapshot data structure for sm.c */ struct sm_snap smreg_info;int scsi_reset = ZERO;#define FAIL -1 #define OK 0 /* * Open the SCSI host adapter. * if found, return (OK=0), FAIL=-1 otherwise. */intsmopen(h_sip) register struct host_saioreq *h_sip;{ register struct scsi_sm_reg *smr; register struct udc_table *dvma; register int i, j; struct idprom id; int base; int scsi_nstd; enum MAPTYPES space; u_long dvmastat; if (idprom(IDFORM_1, &id) == IDFORM_1) { space = MAP_OBIO; scsi_nstd = 1; DPRINTF1("smopen: id.machine= %x\n", id.id_machine); switch (id.id_machine) {#ifdef sun3x case IDM_SUN3X_HYDRA: base = HYDRA_SCSI_BASE; i = HYDRA; break;#endif sun3x#ifdef sun4 case IDM_SUN4_STINGRAY: base = STINGRAY_SCSI_BASE; i = STINGRAY; break;#endif sun4 default: EPRINTF1("smopen: unknown machine type= %x\n", id.id_machine); /* other configuration not supported */ return(FAIL); } } else { /* unknown id type not supported */ EPRINTF1("smopen: UNKNOWN id type= %x\n", idprom(IDFORM_1, &id)); return(FAIL); } DPRINTF1("smopen: ctlr= %x\n", h_sip->ctlr); /* get base address of registers */ if (h_sip->ctlr < scsi_nstd) { h_sip->ctlr = base + (h_sip->ctlr * SM_SIZE); } else { EPRINTF2("smopen: invalid cltr_num= %x, busid= %x\n", h_sip->ctlr, h_sip->unit); return(FAIL); } DPRINTF1("smopen: REG_base= %x\n", h_sip->ctlr); DEBUG_DELAY(1000000); /* now map it in */ h_sip->devaddr = devalloc(space, h_sip->ctlr, sizeof(struct scsi_sm_reg)); if (h_sip->devaddr == ZERO) { EPRINTF("smopen: Can not allocate ESP space\n"); return(FAIL); } DPRINTF1("smopen: sm_addr = %x\n", h_sip->devaddr); /* allocate dma resources for on-board host */ h_sip->dmaaddr = h_sip->devaddr + STINGRAY_DMA_OFFSET; smr = (struct scsi_sm_reg *)h_sip->devaddr; dvma = (struct udc_table *)h_sip->dmaaddr;#ifdef sun4 DPRINTF1("smopen: peeking DVMA's ctl_stat @ %x\n", &dvma->ctl_stat);/* I only modify the lib/sun4/probe.s */ if ((peekl((long *)&(dvma->ctl_stat))) == -1) { EPRINTF1("smopen: peek on DVMA-scsi dma_addr= %x FAILED\n", &(dvma->ctl_stat)); DEBUG_DELAY(1000000); return(FAIL); } DPRINTF1("smopen: DVMA exists, reg_stat= %x\n", dvma->ctl_stat);#endif sun4 DEBUG_DELAY(1000000); dvmastat = dvma->ctl_stat; if (dvmastat & DVMA_REQPEND) { EPRINTF1("smopen: DVMA-scsi req_pend stuck, stat= %x\n", dvmastat); return(FAIL); } if (dvmastat & DVMA_RESET) { DPRINTF1("smopen: DVMA reset asserted, stat= %x\n", i); /* attempt to clear it, if not successful, error return */ dvma->ctl_stat = ZERO; for (i = 0; i < LOOP_2MSEC; i++); dvmastat = dvma->ctl_stat; if (dvmastat & DVMA_RESET) { EPRINTF1("smopen: DVMA-scsi reset stuck, stat= %x\n", dvmastat); return(FAIL); } DPRINTF1("smopen: deasserted DVMA reset, stat= %x\n", i); } /* write/read/compare DVMA 's address reg */ dvmastat = DVMA_TPATTERN; dvma->dma_addr = dvmastat; DPRINTF2("smopen: DVMA test, wr= %x, rd= %x\n", dvmastat, dvma->dma_addr); if (dvma->dma_addr != dvmastat) { EPRINTF2("smopen: DVMA-scsi mismatched dma_addr, wr= %x, rd= %x\n", i, dvma->dma_addr); return(FAIL); } dvma->dma_addr = ZERO; DPRINTF2("smopen: DVMA-scsi PASSED, stat= %x, addr= %x\n", dvma->ctl_stat, dvma->dma_addr); DEBUG_DELAY(1000000); /* check existence and operational status of DVMA before */ /* checking on ESP. If scsi_reset in DVMA is asserted, the */ /* ESP register will not be accessible and DVMA itself is */ /* NOT in a operational state */ /* Check ESP existence -- peek on "ESP reg_xcnt_lo" */#ifdef sun4 DPRINTF1("smopen: peeking ESP's xcnt_lo @ %x\n", &ESP_RD.xcnt_lo);/* I only modify the lib/sun4/probe.s */ if ((peekc((u_char *)&(ESP_RD.xcnt_lo))) == -1) { EPRINTF1("smopen: peek on ESP's addr= %x FAILED\n", &ESP_RD.xcnt_lo); DEBUG_DELAY(1000000); return(FAIL); } DPRINTF1("smopen: ESP exists, reg_conf= %x\n", ESP_RD.conf);#endif sun4 /* perform a simple write, read and compare validation test to "ESP reg_conf". If error, return */ i = 0x55; ESP_WR.conf = i; j = ESP_RD.conf; DPRINTF2("smopen: ESP wr= %x, rd= %x\n", i, j); if ((u_char)i != (u_char)j) { DEBUG_DELAY(1000000); return(FAIL); } i = 0xaa; ESP_WR.conf = i; j = ESP_RD.conf; DPRINTF2("smopen: ESP wr: = %x, rd= %x\n", i, j); DEBUG_DELAY(1000000); if ((u_char)i != (u_char)j) { DEBUG_DELAY(1000000); return(FAIL); } i = ZERO; ESP_WR.conf = i; j = ESP_RD.conf; if ((u_char)i != (u_char)j) { DPRINTF2("smopen: ESP FAILED, wr= %x, rd= %x\n", i, j); DEBUG_DELAY(1000000); return(FAIL); } /* Perform a simple write, read & compare validation test to ESP_II */ i = ESP_TPATTERN; ESP_WR.conf2 = i; /* write */ j = ESP_RD.conf2; /* read */ if ((u_char)i == (u_char)j) { /* compare */ ESP_WR.conf2 = ZERO; /* make ESP 2 function as ESP */ DPRINTF("smopen: ESP_2 found, config to ESP\n"); } else DPRINTF("smopen: ESP_2 not found\n"); DEBUG_DELAY(1000000); /* set all the routine pointers */ DPRINTF("smopen: setting doit() pointer\n"); h_sip->doit = smdoit; h_sip->reset = sm_reset; if (scsi_reset == ZERO) { /* need to reset SCSI bus when call from le() boot, since */ /* firmware will not call scsi driver to reset the bus */ sm_reset(h_sip, RESET_ALL_SCSI); scsi_reset++; } else { sm_reset(h_sip, RESET_INT_ONLY); } DPRINTF1("smopen: done, smr= %x\n", smr); return(OK); /* successfully opened */}/* * Write a command to the SCSI bus. * * The supplied h_sip is the one opened by smopen(). * DMA is done based on h_sip->ma and h_sip->cc. * * Returns -1 for error, otherwise returns the residual count * * FIXME, this must be accessed via a boottab vector, * to allow host adap to switch. * Must pass cdb, scb in h_sip somewhere...*/intsmdoit(cdb, scb, h_sip) struct scsi_cdb *cdb; struct scsi_scb *scb; struct host_saioreq *h_sip;{ register struct scsi_sm_reg *smr; register struct sm_snap *smsnap = &smreg_info; register struct udc_table *dvma; register u_char *cp; register int i, size; u_long toutcnt; /* get to scsi control logic registers */ smr = (struct scsi_sm_reg *)h_sip->devaddr; dvma = (struct udc_table *)h_sip->dmaaddr; DPRINTF("smdoit: POLL/NO_disconnect mode\n"); cp = (u_char *)cdb; size = sc_cdb_size[CDB_GROUPID(*cp)]; /* Write "ESP reg_fifo" with all command bytes */ DPRINTF("smdoit: cmd byte="); for (i = 0; i < size; i++) { DPRINTF1(" %x", *cp); ESP_WR.fifo_data = *cp++; } DPRINTF1("\nsmdoit: fifo_flag @= %x\n", ESP_RD.fifo_flag); DEBUG_DELAY(1000000); DPRINTF1("smdoit: ready to send cmd= %x\n", cdb->scc_cmd); switch (cdb->scc_cmd) { case SC_READ: case SC_REQUEST_SENSE: case SC_INQUIRY: case SC_MODE_SENSE: smsnap->sync_chk = SM_RECV_DATA; break; case SC_WRITE: case SC_MODE_SELECT: case SC_WRITE_FILE_MARK:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -