📄 sf.c
字号:
}/* * This routine called to see whether unit is (still) there. Must not * be called when un->un_sbufp is in use, and must not be called with * an unattached disk. Soft state of disk is restored to what it was * upon entry- up to caller to set the correct state. * */static intsf_unit_ready(dev)dev_t dev;{ struct scsi_device *devp = sfunits[SFUNIT(dev)]; struct scsi_floppy *un = UPTR; auto struct dk_cmd cblk, *com = &cblk; u_char state; un->un_last_state = un->un_state; un->un_state = SF_STATE_OPENING; com->dkc_cmd = SCMD_REZERO_UNIT; com->dkc_flags = DK_SILENT; com->dkc_blkno = 0; com->dkc_secnt = 0; com->dkc_bufaddr = 0; com->dkc_buflen = 0; if (sfioctl_cmd(dev,com)) { state = un->un_state; un->un_last_state = un->un_state; un->un_state = state; return (0); } state = un->un_state; un->un_last_state = un->un_state; un->un_state = state; return (1);}static intsf_get_density(dev)dev_t dev;{ struct scsi_device *devp = sfunits[SFUNIT(dev)]; struct scsi_floppy *un = UPTR; struct ccs_modesel_head *hp = (struct ccs_modesel_head *) un->un_mode; auto struct dk_cmd cblk, *com = &cblk; caddr_t dblk; register int i, dens, rval = -1; u_char state; un->un_last_state = un->un_state; un->un_state = SF_STATE_OPENING; dblk = kmem_alloc((unsigned)SECSIZE); if (dblk == 0) { printf("%s%d: unable to alloc space\n",DNAME,DUNIT); return (rval); } for (dens = 0; media_types[dens] != 0; dens++) { if (sf_get_mode(dev,com) == 0) { break; } if (dens == 0) media_types[dens] = hp->medium; hp->medium = media_types[dens]; DPRINTF_IOCTL("%s%d: trying to set density %x\n",DNAME,DUNIT, hp->medium); if (sf_set_shortmode(dev,com)) { DPRINTF_IOCTL("%s%d: mode select fails; key %x\n", DNAME,DUNIT,un->un_status); continue; } com->dkc_cmd = SCMD_READ; com->dkc_flags = DK_SILENT; com->dkc_blkno = 0; com->dkc_secnt = 1; com->dkc_bufaddr = dblk; com->dkc_buflen = SECSIZE | (1<<31); if (sfioctl_cmd(dev,com) == 0) { rval = 0; DPRINTF_IOCTL("%s%d: test read succeeds; dens=%x\n", DNAME,DUNIT,media_types[dens]&0xff); break; } DPRINTF_IOCTL("%s%d: test read fails; key %x\n",DNAME,DUNIT, un->un_status); } (void) kmem_free (dblk, (unsigned) SECSIZE); state = un->un_state; un->un_last_state = un->un_state; un->un_state = state; return (rval);}static intsf_get_mode(dev,com)dev_t dev;struct dk_cmd *com;{ struct scsi_device *devp = sfunits[SFUNIT(dev)]; struct scsi_floppy *un = UPTR; com->dkc_cmd = SCMD_MODE_SENSE; com->dkc_flags = DK_SILENT; com->dkc_blkno = 0x5; com->dkc_secnt = 0; com->dkc_bufaddr = un->un_mode; com->dkc_buflen = MSIZE | (1<<31);/* to avoid an as_fault */ bzero(un->un_mode,MSIZE); if (sfioctl_cmd(dev,com)) { return (0); } if (DEBUGGING_ALL) { register i; char *p = un->un_mode; printf("mode sense data:\n"); for (i = 0; i < MSIZE; i++) { printf(" 0x%x",p[i]&0xff); if (((i+1)&0xf) == 0) printf("\n"); } printf("\n"); } return (1);}static intsf_set_shortmode(dev,com)dev_t dev;struct dk_cmd *com;{ struct scsi_device *devp = sfunits[SFUNIT(dev)]; struct scsi_floppy *un = UPTR; struct ccs_modesel_head *hp = (struct ccs_modesel_head *) un->un_mode; hp->block_desc_length = 0; com->dkc_cmd = SCMD_MODE_SELECT; com->dkc_flags = DK_SILENT; com->dkc_blkno = 0; com->dkc_secnt = 0; com->dkc_bufaddr = un->un_mode; com->dkc_buflen = 4 | (1<<31); if (sfioctl_cmd(dev,com)) { return (0); } return (1);}static intsf_set_density(dev)dev_t dev;{ return (0);}/************************************************************************ ************************************************************************ * * * * * Interrupt Service Routines * * * * * ************************************************************************ ************************************************************************/staticsfrestart(arg)caddr_t arg;{ struct scsi_device *devp = (struct scsi_device *) arg; struct buf *bp; register s = splr(sfpri); printf("sfrestart\n"); if ((bp = UPTR->un_utab.b_forw) == 0) { printf("%s%d: busy restart aborted\n",DNAME,DUNIT); } else { struct scsi_pkt *pkt; if (UPTR->un_state == SF_STATE_SENSING) { pkt = UPTR->un_rqs; } else { pkt = BP_PKT(bp); } if (pkt_transport(pkt) == 0) { printf("%s%d: restart transport failed\n",DNAME,DUNIT); UPTR->un_state = UPTR->un_last_state; bp->b_resid = bp->b_bcount; bp->b_flags |= B_ERROR; sfdone(devp); } } (void) splx(s);}/* * Command completion processing * */static voidsfintr(pkt)struct scsi_pkt *pkt;{ register struct scsi_device *devp; register struct scsi_floppy *un; register struct buf *bp; register action; if (pkt->pkt_flags & FLAG_NOINTR) { printf("sfintr:internal error - got a non-interrupting cmd\n"); return; } DPRINTF("sfintr:\n"); bp = (struct buf *) pkt->pkt_private; ASSERT(bp != NULL); devp = sfunits[SFUNIT(bp->b_dev)]; un = UPTR; if(bp != un->un_utab.b_forw) { printf("sfintr: buf not on queue?"); panic("sfintr1"); } if (pkt->pkt_reason != CMD_CMPLT) { action = sf_handle_incomplete(devp); /* * At this point we know that the command was successfully * completed. Now what? */ } else if (un->un_state == SF_STATE_SENSING) { /* * okay. We were running a REQUEST SENSE. Find * out what to do next. */ ASSERT(pkt == un->un_rqs); un->un_state = un->un_last_state; un->un_last_state = un->un_state; pkt = BP_PKT(bp); action = sf_handle_sense(devp); /* * Okay, we weren't running a REQUEST SENSE. Call a routine * to see if the status bits we're okay. As a side effect, * clear state for this device, set non-error b_resid values, etc. * If a request sense is to be run, that will happen. */ } else { action = sf_check_error(devp); } switch(action) { case COMMAND_DONE_ERROR: un->un_err_severe = DK_FATAL; un->un_err_resid = bp->b_resid = bp->b_bcount; bp->b_flags |= B_ERROR; /* FALL THRU */ case COMMAND_DONE: sfdone(devp); break; case QUE_SENSE: un->un_last_state = un->un_last_state; un->un_state = SF_STATE_SENSING; un->un_rqs->pkt_private = (opaque_t) bp; bzero((caddr_t)devp->sd_sense,SENSE_LENGTH); if (pkt_transport(un->un_rqs) == 0) { panic("sfintr: transport of request sense fails"); /*NOTREACHED*/ } break; case QUE_COMMAND: if (pkt_transport(BP_PKT(bp)) == 0) { printf("sfintr: requeue of command fails\n"); un->un_err_resid = bp->b_resid = bp->b_bcount; bp->b_flags |= B_ERROR; sfdone(devp); } break; case JUST_RETURN: break; }}static intsf_handle_incomplete(devp)struct scsi_device *devp;{ static char *notresp = "%s%d: disk not responding to selection\n"; register rval = COMMAND_DONE_ERROR; struct scsi_floppy *un = UPTR; struct buf *bp = un->un_utab.b_forw; struct scsi_pkt *pkt = (un->un_state == SF_STATE_SENSING)? un->un_rqs : BP_PKT(bp); if (pkt == un->un_rqs) { un->un_state = un->un_last_state; un->un_last_state = SF_STATE_SENSING; if (un->un_retry_ct++ < SF_RETRY_COUNT) rval = QUE_SENSE; } else if (bp == un->un_sbufp && (un->un_soptions & DK_ISOLATE)) { rval = COMMAND_DONE_ERROR; } else if (un->un_retry_ct++ < SF_RETRY_COUNT) { rval = QUE_COMMAND; } if (pkt->pkt_state == STATE_GOT_BUS && rval == COMMAND_DONE_ERROR) { /* * Looks like someone turned off this shoebox. */ printf(notresp,DNAME,DUNIT); un->un_last_state = un->un_state; un->un_state = SF_STATE_DETACHING; } else if (bp != un->un_sbufp || (un->un_soptions & DK_SILENT) == 0) { printf("%s%d: command transport failed: reason '%s': %s\n", DNAME,DUNIT,scsi_rname(pkt->pkt_reason), (rval == COMMAND_DONE_ERROR)?"giving up":"retrying"); } return rval;}static intsf_handle_sense(devp)register struct scsi_device *devp;{ register struct scsi_floppy *un = UPTR; register struct buf *bp = un->un_utab.b_forw; struct scsi_pkt *pkt = BP_PKT(bp), *rqpkt = un->un_rqs; register rval = COMMAND_DONE_ERROR; int severity, amt, i; char *p; static char *hex =" 0x%x"; if (SCBP(rqpkt)->sts_busy) { printf ("%s%d: busy unit on request sense\n",DNAME,DUNIT); if (un->un_retry_ct++ < SF_RETRY_COUNT) { timeout (sfrestart, (caddr_t)devp, SFTIMEOUT); rval = JUST_RETURN; } return(rval); } if (SCBP(rqpkt)->sts_chk) { printf ("%s%d: Check Condition on REQUEST SENSE\n",DNAME,DUNIT); return (rval); } amt = SENSE_LENGTH - rqpkt->pkt_resid; if ((rqpkt->pkt_state&STATE_XFERRED_DATA) == 0 || amt == 0) { printf("%s%d: Request Sense couldn't get sense data\n",DNAME, DUNIT); return (rval); } /* * Now, check to see whether we got enough sense data to make any * sense out if it (heh-heh). */ if (amt < sizeof (struct scsi_extended_sense)) { if (amt < sizeof (struct scsi_sense)) { printf("%s%d: couldn't get enough sense information\n", DNAME,DUNIT); return (rval); } if (devp->sd_sense->es_class != CLASS_EXTENDED_SENSE) { p = (char *) devp->sd_sense; printf("%s%d: undecoded sense information:"); for (i = 0; i < amt; i++) { printf(hex,*(p++)&0xff); } printf("; assuming a fatal error\n"); return (rval); } } un->un_status = devp->sd_sense->es_key; un->un_err_code = devp->sd_sense->es_code; if (devp->sd_sense->es_valid) { un->un_err_blkno = (devp->sd_sense->es_info_1 << 24) | (devp->sd_sense->es_info_2 << 16) | (devp->sd_sense->es_info_3 << 8) | (devp->sd_sense->es_info_4); } else { un->un_err_blkno = bp->b_blkno; } if (DEBUGGING_ALL || sf_error_reporting == SDERR_ALL) { p = (char *) devp->sd_sense; printf("%s%d:sdata:",DNAME,DUNIT); for (i = 0; i < amt; i++) { printf(hex,*(p++)&0xff); } printf("\n cmd:"); p = pkt->pkt_cdbp; for (i = 0; i < CDB_SIZE; i++) printf(hex,*(p++)&0xff); printf("\n"); } switch (un->un_status) { case KEY_NO_SENSE: un->un_err_severe = DK_NOERROR; severity = SDERR_RETRYABLE; rval = SDERR_INFORMATIONAL; break; case KEY_RECOVERABLE_ERROR: bp->b_resid = pkt->pkt_resid; un->un_err_severe = DK_CORRECTED; un->un_retry_ct = 0; severity = SDERR_RECOVERED; rval = COMMAND_DONE; break; case KEY_NOT_READY: case KEY_MEDIUM_ERROR: case KEY_HARDWARE_ERROR: case KEY_ILLEGAL_REQUEST: case KEY_VOLUME_OVERFLOW: case KEY_WRITE_PROTECT: case KEY_BLANK_CHECK: un->un_err_severe = DK_FATAL; severity = SDERR_FATAL; rval = COMMAND_DONE_ERROR; break; case KEY_ABORTED_COMMAND: severity = SDERR_RETRYABLE; rval = QUE_COMMAND; break; case KEY_UNIT_ATTENTION: { bp->b_resid = pkt->pkt_resid; un->un_err_severe = DK_NOERROR; un->un_retry_ct = 0; severity = SDERR_INFORMATIONAL; rval = QUE_COMMAND; break; } default: /* * Undecoded sense key. Try retries and hope * that will fix the problem. Otherwise, we're * dead. */ printf("%s%d: Sense Key '%s'\n",DNAME,DUNIT, sense_keys[un->un_status]); if (un->un_retry_ct++ < SF_RETRY_COUNT) { un->un_err_severe = DK_RECOVERED; severity = SDERR_RETRYABLE; rval = QUE_COMMAND; } else { un->un_err_severe = DK_FATAL; severity = SDERR_FATAL; rval = COMMAND_DONE_ERROR; } } if (rval == QUE_COMMAND && bp == un->un_sbufp && (un->un_soptions & DK_DIAGNOSE) == 0) { un->un_err_severe = DK_FATAL; rval = COMMAND_DONE_ERROR; } if (bp == un->un_sbufp) { if ((un->un_soptions & DK_SILENT) == 0) { sferrmsg(devp,severity); } } else if (DEBUGGING_ALL || severity >= sf_error_reporting) { sferrmsg(devp,severity); } return (rval);}static intsf_check_error(devp)register struct scsi_device *devp;{ register struct scsi_floppy *un = UPTR; struct buf *bp = un->un_utab.b_forw; register struct scsi_pkt *pkt = BP_PKT(bp); register action; if (SCBP(pkt)->sts_busy) { printf("%s%d: unit busy\n",DNAME,DUNIT); if (un->un_retry_ct++ < SF_RETRY_COUNT) { timeout(sfrestart,(caddr_t)devp,SFTIMEOUT); action = JUST_RETURN; } else { printf("%s%d: device busy too long\n",DNAME,DUNIT); action = COMMAND_DONE_ERROR; } } else if (SCBP(pkt)->sts_chk) { DPRINTF("%s%d: check condition\n",DNAME,DUNIT); action = QUE_SENSE; } else { /* * pkt_resid will reflect, at this point, a residual * of how many bytes left to be transferred there were * */ bp->b_resid = pkt->pkt_resid; action = COMMAND_DONE; un->un_err_severe = DK_NOERROR; un->un_retry_ct = 0; } return (action);}/************************************************************************ ************************************************************************ * * * * * Error Printing * * * * * ************************************************************************ ************************************************************************/static char *sf_cmds[] = { "\000test unit ready", /* 0x00 */ "\001rezero", /* 0x01 */ "\003request sense", /* 0x03 */ "\004format", /* 0x04 */ "\007reassign", /* 0x07 */ "\010read", /* 0x08 */ "\012write", /* 0x0a */ "\013seek", /* 0x0b */ "\022inquiry", /* 0x12 */ "\025mode select", /* 0x15 */ "\026reserve", /* 0x16 */ "\027release", /* 0x17 */ "\030copy", /* 0x18 */ "\032mode sense", /* 0x1a */ "\033start/stop", /* 0x1b */ "\036door lock", /* 0x1e */ "\067read defect data", /* 0x37 */ NULL};static voidsferrmsg(devp, level)register struct scsi_device *devp;int level;{ static char *error_classes[] = { "All ", "Unknown ", "Informational", "Recovered ", "Retryable ", "Fatal " }; char *class; struct scsi_pkt *pkt; class = error_classes[level]; pkt = BP_PKT(UPTR->un_utab.b_forw); printf("%s%d:\tError for command '%s'\n",DNAME,DUNIT, scsi_cmd_decode(CDBP(pkt)->scc_cmd,sf_cmds)); printf(" \tError Level: %s Block: %d\n",class,UPTR->un_err_blkno); printf(" \tSense Key: %s\n",sense_keys[devp->sd_sense->es_key]); if (devp->sd_sense->es_code) { printf(" \tVendor Unique Error Code: %x", devp->sd_sense->es_code); } printf("\n");}#endif NSF > 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -