📄 st.c
字号:
stclose(sip) register struct saioreq *sip;{ register struct stparam *stp; EPRINTF("stclose:\n"); stp = (struct stparam *) sip->si_devdata; if (stp->st_lastcmd == SC_WRITE) (void) stcmd(SC_WRITE_FILE_MARK, sip, 0); sc_reset = 0; return (0);}/* * Perform a read or write of the SCSI tape. */ststrategy(sip, rw) register struct saioreq *sip; int rw;{ register struct stparam *stp; DPRINTF("ststrategy:\n"); sc_reset = 1; stp = (struct stparam *) sip->si_devdata; if (stp->st_eof) { stp->st_eof = 0; return (0); } DPRINTF2("ststrategy: addr= 0x%x size= 0x%x\n", (int)(sip->si_ma), sip->si_cc); rw = stcmd((rw == WRITE ? SC_WRITE : SC_READ), sip, 1); return (rw);}/* * Execute a scsi tape command */static intstcmd(cmd, sip, errprint) short cmd; register struct saioreq *sip; int errprint;{ register struct stparam *stp; register struct host_saioreq *h_sip; /* Sip for host adapter */ register struct st_ms_mspl *mode; register struct st_sense *ems; register struct sysgen_sense *scs; struct scsi_cdb6 cdb, scdb; struct scsi_scb scb, sscb; char *buf; int density; int r, cc; DPRINTF("stcmd:\n");AGAIN: stp = (struct stparam *)sip->si_devdata; h_sip = &stp->h_sip; /* host adapter */ h_sip->unit = stp->st_target; buf = sip->si_ma; /* Set up cdb */ bzero((char *) &scb, sizeof scb); bzero((char *) &cdb, CDB_GROUP0); stp->st_lastcmd = cmd; cdb.cmd = cmd; cdb.lun = stp->st_unit; h_sip->cc = 0; h_sip->ma = 0; DPRINTF2("stcmd: cmd= 0x%x lun= 0x%x\n", cdb.cmd, cdb.lun); /* Some fields in the cdb are command specific */ switch (cmd) { case SC_READ: h_sip->dma_dir = SC_RECV_DATA; if (stp->st_dev_bsize == 0) { DPRINTF1("stcmd: variable read (0x%x)\n", sip->si_cc); cc = h_sip->cc = sip->si_cc; } else { DPRINTF1("stcmd: read (0x%x)\n", sip->si_cc); cc = h_sip->cc = ROUNDUP(sip->si_cc); cc = cc / stp->st_dev_bsize; cdb.t_code = 1; }STCMD_RD: cdb.mid_count = (cc >> 8) & 0xFF; cdb.low_count = cc & 0xFF; if (buf >= DVMA_BASE) { h_sip->ma = buf; DPRINTF1("stcmd: DVMA addr= 0x%x\n", h_sip->ma); } else { h_sip->ma = BUF; DPRINTF("stcmd: BUF addr\n"); } if (cc == 0) h_sip->dma_dir = SC_NO_DATA; break; case SC_WRITE: h_sip->dma_dir = SC_SEND_DATA; if (buf < DVMA_BASE) { DPRINTF("stcmd: write bcopy\n"); bcopy(buf, BUF, sip->si_cc); } if (stp->st_dev_bsize == 0) { DPRINTF1("stcmd: variable write (0x%x)\n", sip->si_cc); cc = h_sip->cc = sip->si_cc; } else { DPRINTF1("stcmd: write (0x%x)\n", sip->si_cc); cc = h_sip->cc = ROUNDUP(sip->si_cc); cc = cc / stp->st_dev_bsize; cdb.t_code = 1; } goto STCMD_RD; /* break; */ case SC_MODE_SENSE: DPRINTF("stcmd: mode sense\n"); h_sip->dma_dir = SC_RECV_DATA; h_sip->cc = sip->si_cc = sizeof (struct st_ms_mspl); cdb.low_count = h_sip->cc & 0xFF; h_sip->ma = BUF; bzero((char *)h_sip->ma, sizeof (struct st_ms_mspl)); break; case SC_QIC11: EPRINTF("stcmd: low density (qic-11)\n"); sip->si_cc = 0; h_sip->dma_dir = SC_NO_DATA; if (ISASYSGEN(stp)) { cdb.cmd = SC_QIC02; cdb.high_count = ST_SYSGEN_QIC11; } else { density = ST_EMULEX_QIC11; goto MODE; } break; case SC_QIC24: EPRINTF("stcmd: high density (qic-24)\n"); sip->si_cc = 0; h_sip->dma_dir = SC_NO_DATA; if (ISASYSGEN(stp)) { cdb.cmd = SC_QIC02; cdb.high_count = ST_SYSGEN_QIC24; } else { density = ST_EMULEX_QIC24; goto MODE; } break; case SC_MODE_SELECT:MODE: cdb.cmd = SC_MODE_SELECT; mode = (struct st_ms_mspl *)STSBUF; bzero((char *)mode, sizeof(*mode)); mode->bufm = 1; mode->bd_len = MS_BD_LEN; mode->density = density; mode->mid_bl = (stp->st_dev_bsize >> 8) & 0xff; mode->low_bl = stp->st_dev_bsize & 0xff; h_sip->ma = (char *)mode; h_sip->dma_dir = SC_SEND_DATA; sip->si_cc = h_sip->cc = cdb.low_count = sizeof (struct st_ms_mspl); break; case SC_SPACE_FILE: EPRINTF("stcmd: space file\n"); cdb.cmd = SC_SPACE_REC; /* Real SCSI cmd */ cdb.t_code = 1; /* Space file, not rec */ cdb.low_count = 1; /* Space 1 file */ sip->si_cc = 0; h_sip->dma_dir = SC_NO_DATA; break; case SC_WRITE_FILE_MARK: DPRINTF("stcmd: write file mark\n"); cdb.low_count = 1; sip->si_cc = 0; h_sip->dma_dir = SC_NO_DATA; break; case SC_REQUEST_SENSE: DPRINTF("stcmd: request sense\n"); cdb.low_count = h_sip->cc = sip->si_cc; h_sip->ma = buf; h_sip->dma_dir = SC_RECV_DATA; /* bzero((char *)buf, sizeof (struct st_ms_mspl)); */ break; case SC_INQUIRY: EPRINTF("stcmd: inquiry\n"); h_sip->cc = sip->si_cc = sizeof (struct scsi_inquiry_data); cdb.low_count = h_sip->cc; h_sip->dma_dir = SC_RECV_DATA; h_sip->ma = buf; bzero((char *)buf, h_sip->cc); break; case SC_TEST_UNIT_READY:#ifdef STDEBUG DPRINTF("stcmd: test unit\n"); sip->si_cc = 0; h_sip->dma_dir = SC_NO_DATA; break;#endif STDEBUG case SC_REWIND: DPRINTF("stcmd: rewind\n"); sip->si_cc = 0; h_sip->dma_dir = SC_NO_DATA; break; default: SC_ERROR1("st: unknown command (0x%x)\n", cdb.cmd); return (0); } /* Execute the command */ r = (*h_sip->doit)(&cdb, &scb, h_sip); DPRINTF2("stcmd: r = 0x%x (0x%x)\n", r, sip->si_cc); /* Host adapter error */ if (r < 0) { EPRINTF("stcmd: SCSI bus error\n"); return (r); } /* Allow for tape blocking */ if (r > sip->si_cc) { EPRINTF1("stcmd: round to 0x%x\n", sip->si_cc); r = sip->si_cc; } /* Device busy error */ if(scb.busy) { EPRINTF("stcmd: busy\n"); DELAY(2000000); goto AGAIN; } if (cmd == SC_READ && buf < DVMA_BASE) { DPRINTF("stcmd: read bcopy\n"); if (min(sip->si_cc, r)) bcopy(BUF, buf, (min(sip->si_cc, r))); } /* We may need to get sense data */ if (scb.chk) { EPRINTF("stcmd: check condition\n"); bzero((char *) &sscb, sizeof(sscb)); bzero((char *) &scdb, CDB_GROUP0); scdb.cmd = SC_REQUEST_SENSE; scdb.lun = stp->st_unit; if (ISASYSGEN(stp)) { h_sip->cc = scdb.low_count = ST_SYSGEN_SENSE_LEN; } else { h_sip->cc = scdb.low_count = ST_EMULEX_SENSE_LEN; } h_sip->ma = STSBUF; h_sip->dma_dir = SC_RECV_DATA; (void) (*h_sip->doit)(&scdb, &sscb, h_sip); /* Process Sysgen tape drive errors */ if (ISASYSGEN(stp)) { scs = (struct sysgen_sense *)STSBUF; stp->st_eof = 1; /* No tape */ if (scs->no_cart) { EPRINTF("stcmd: not ready\n"); return (-2); } /* QIC-24 */ if (scs->no_data != 0) { EPRINTF("stcmd: blank check\n"); return (-2); } /* EOF */#ifdef STDEBUG if (scs->file_mark) EPRINTF("stcmd: eof\n");#endif STDEBUG /* Other errors */ if ((scs->file_mark == 0) && errprint) { SC_ERROR1("st: error %x\n", *(u_short *)&STSBUF[SENSELOC]); } return (r); /* Process MT-02 and CCS tape drive errors */ } else { ems = (struct st_sense *)STSBUF; /* Blank Check error */ if (ems->key == SC_BLANK_CHECK) { EPRINTF("stcmd: blank check\n"); stp->st_eof = 1; return (-2); /* Soft error */ } else if (ems->key == SC_RECOVERABLE_ERROR) { EPRINTF("stcmd: soft error\n"); return (r ? r : 1); /* EOF error */ }else if (ems->fil_mk) { EPRINTF("stcmd: eof\n"); stp->st_eof = 1; return (r); /* Illegal length error */ } else if (ems->ili) { EPRINTF("stcmd: illegal length\n"); return (r ? r : 1); /* Other errors */ } else if(errprint) { SC_ERROR1("st: sense key = %x", ems->key);#ifdef STDEBUG SC_ERROR1(" (%s)", st_key_error_str[ems->key]);#endif STDEBUG SC_ERROR1(" error = %x\n", ems->error); stp->st_eof = 1; return (-1); } } } if (r >= sip->si_cc) { /* Normal completion exit */ return (sip->si_cc ? sip->si_cc : 1); } else { /* Error exit */ if (errprint) { EPRINTF1("stcmd: short transfer (0x%x)\n", r); } return (r); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -