📄 sd.c
字号:
break; /****************************************/ /* */ /* REQUEST SENSE analysis */ /* */ /****************************************/ case SDCS_RSENSE: case SDCS_PREVRMB|SDCS_RSENSE: case SDCS_ECC|SDCS_RASREAD|SDCS_RSENSE: case SDCS_ECC|SDCS_RASWRITE|SDCS_RSENSE: case SDCS_ECCOFF|SDCS_RSENSE: case SDCS_ECCOFF|SDCS_RASBLK|SDCS_RSENSE: case SDCS_ECCOFF|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE: case SDCS_ECC|SDCS_RASBLK|SDCS_RSENSE: case SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE: if (tstatus != TGST_GOOD) { printf("sd%d: bad target status 0x%x\n", unit, sc->sc_tstatus); goto sdintr_error; } /* * error message print out */ code = sderrordisp(sce, ii); if ((sdc->sdc_state == (SDCS_ECC|SDCS_RASBLK|SDCS_RSENSE)) || (sdc->sdc_state == (SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE))) { printf("sd%d: cannot reassign block %d\n", unit, sdd->sdd_badsect); goto sdintr_error; } if (sdc->sdc_state == (SDCS_PREVRMB|SDCS_RSENSE)) { if (sce->sce_skey == 0x2) { /* * Not ready */ sdc->sdc_state = SDCS_PREVRMB; timeout(delay_medrmv, (caddr_t)ii, hz); return; } } /* */ /* RSENSE error handler */ /* */ switch (code) { /********************************/ /* continue */ /********************************/ /* NO SENSE */ case 0x00: /* No Additional Sense Information */ /* RECOVERED ERROR */ case 0x38: /* Recovered with Auto-Reallocation */ sdc->sdc_state &= ~SDCS_RSENSE; goto check_target_status; /********************************/ /* continue or error */ /********************************/ /* ILLEGAL REQUEST */ case 0x21: /* illegal Logical Block Address */ if (&st->sizes[dev2part(bp->b_dev)] == NULL) goto sdintr_error; if (bp->b_bcount > 0) { bp->b_resid = bp->b_bcount - (sdd->sdd_badsect * sdd->sdd_sectsize - (st->sizes[dev2part(bp->b_dev)].sd_blkoff + dkblock(bp)) * DEV_BSIZE); } if (bp->b_resid >= bp->b_bcount || bp->b_resid <= 0) { /* * all I/O failure */ bp->b_resid = bp->b_bcount; goto sdintr_error; } /* Ignore error */ break; /* MEDIUM ERROR */ case 0x31: /* Medium Format Corrupted */ sdd->sdd_flags |= SDDF_NONFMT; /* Ignore error */ break; /********************************/ /* more retry */ /********************************/ /* MEDIUM or RECOVERED ERROR */ case 0x10: /* ID CRC Error */ case 0x12: /* No Address Mark found in ID field */ case 0x13: /* No Address Mark found in Data field */ case 0x14: /* No recode found */ /* H/W or MEDIUM or RECOVERED ERROR */ case 0x15: /* Seek Positioning Error */ if (sd_ignore_error) { sdc->sdc_state = SDCS_NORMAL; goto check_target_status; } /* fall through */ /* H/W ERROR */ case 0x01: /* No Index/Address Mark Found signal */ case 0x02: /* No Seek Complete */ case 0x06: /* No Track Zero found */ /* H/W ERROR or RECOVERED ERROR */ case 0x03: /* Write Fault */ case 0x08: /* Logical Unit Communication Failure */ case 0x09: /* Track Following Error */ case 0x0b: /* Load/Unload Failure */ case 0x0c: /* Spindle Failure */ case 0x0d: /* Focus Failure */ case 0x0e: /* Tracking Failure */ case 0x0f: /* Drive Initialization Failure */ sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD|SDCS_REZERO; scinit(sc, slave, sdd->sdd_sectsize); /* sc_cdb */ sc->sc_opcode = SCOP_REZERO; sddgo(im); return; /********************************/ /* re-allocate & retry */ /********************************/ /* MEDIUM or RECOVERED ERROR */ case 0x11: /* Unrecovered Read Error */ if (sdc->sdc_state & SDCS_RASREAD) {sdintr_lostdata: sdc->sdc_state = SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA; im->im_tab.b_active = 2; scop_rasblk(intr, sc, slave, SCSI_INTEN, sdd->sdd_badsect); sdd->sdd_flags &= ~SDDF_VBADSECT; return; } /* fall through */ /* RECOVERED ERROR */ case 0x17: /* Recovered read data with retries */ case 0x18: /* Recovered read data with ECC */ /* * set ECC ON & more retry */ if (sdc->sdc_firmware & SDCFW_DEFMODE) goto sdintr_ecc; if (sdc->sdc_state & SDCS_RASREAD) goto sdintr_rasblk; sdc->sdc_state = SDCS_ECC; goto sdintr_msel_set; /********************************/ /* unit start & retry */ /********************************/ /* NOT READY */ case 0x04: /* Drive Not Ready */ if (sdc->sdc_state & SDCS_ECC) sdc->sdc_state = SDCS_ECCOFF|SDCS_RETRY; else sdc->sdc_state = SDCS_RETRY; goto sdintr_stst; /********************************/ /* retry */ /********************************/ /* UNIT ATTENTION */ case 0x28: /* Medium Changed */ sdd->sdd_flags &= ~(SDDF_NONFMT |SDDF_SAMEDSK |SDDF_REQ_EJECT |SDDF_XUSE |SDDF_INHRMV |SDDF_ERASEOFF); /* fall through */ case 0x29: /* Power On or Reset or Bus Device Reset */ if (sdc->sdc_firmware & SDCFW_RMB) { /***************************/ /* medium removable device */ /***************************/ sdc->sdc_state = SDCS_PREVRMB; im->im_tab.b_active = 2; scop_medrmv(intr, sc, slave, SCSI_INTEN, SDRMV_PREV); return; } case 0x2a: /* Mode Select Parameter Changed */ case 0x47: /* SCSI interface bus parity error */ if (sdc->sdc_state & SDCS_ECC) { sdc->sdc_state = SDCS_RETRY; goto sdintr_msel_reset; } sdc->sdc_state = SDCS_NORMAL; goto sdintr_exec; /********************************/ /* set error flag */ /********************************/ case 0x40: /* RAM failure */ case 0x41: /* Data Path diagnostic failure */ case 0x42: /* Power On diagnostic failure */ case 0xb2: /* Caddy load/eject failed */ case 0xb4: /* Focus servo failure */ case 0xb5: /* Spindle servo failure */ case 0xb6: /* Caddy load mechanism failed */ goto sdintr_error;/*MO*/ case 0x80: /* Limit Laser Life *//*MO*/ case 0x81: /* Focus Coil Over-current Failure *//*MO*/ case 0x82: /* Tracking Coil Over-current Failure *//*MO*/ case 0x83: /* Temperature Alarm *//*CD*/ /* case 0x80: */ /* Prevent bit is set *//*CD*/ /* case 0x81: */ /* Logical unit is reserved *//*CD*/ /* case 0x82: */ /* End of usr area encountered *//*CD*/ /* case 0x83: */ /* Overlapped commands attempted */ goto sdintr_error; default: /* * error detect, but what shall we do ? */ /* case 0x05: */ /* Drive Not Selected */ /* case 0x07: */ /* Multiple Drives Selected */ /* case 0x0a: */ /* No disk */ /* case 0x1a: */ /* Parameter overrun */ /* case 0x1b: */ /* Synchronous transfer error */ /* case 0x1d: */ /* Compare error */ /* case 0x22: */ /* Illegal function for device type */ /* case 0x23: */ /* Illegal function for Medium type */ /* case 0x25: */ /* Illegal LUN */ /* case 0x27: */ /* Write Protected */ /* case 0x2b: */ /* Firmware has been downloaded */ /* case 0x39: */ /* Automatic Reallocation Failure */ /* case 0x43: */ /* Message Reject Error */ /* case 0x45: */ /* Selection/Reselection failure */ /* case 0x48: */ /* Initiator detected error */ /* case 0x49: */ /* Inappropriate/illegal message */ /* case 0x60: */ /* COPY: STATUS error */ /* case 0x85: */ /* Audio address not valid */ /* case 0xb0: */ /* Caddy not inserted in drive */ /* case 0xb1: */ /* Unable to recover TOC */ /* case 0xb3: */ /* CIRC unrecovered data error(L-EC off) */ /* case 0xc3: */ /* COPY: Illegale CDB length */ /* case 0xc5: */ /* COPY: Catastrophic error */ /* case 0xc6: */ /* COPY: Illegal phase change */ /* case 0xfc: */ /* COPY: MODE SENSE failed */ /* * medium error */ /* case 0x19: */ /* Defect list error */ /* case 0x1c: */ /* Primary Defect List not found */ /* case 0x30: */ /* Incompatible Cartridge */ /* case 0x32: */ /* No Spare Defect Location Available */ /* case 0x3a: */ /* Defect List Update Failure */ /* case 0x3d: */ /* Defect List Not Available */ goto sdintr_error; } /* * No error detected or ignored. */ break; /************************************************/ /* */ /* PREVENT MEDIUM REMOVABLE COMMAND */ /* */ /************************************************/ case SDCS_PREVRMB: if (tstatus == TGST_CC) { sdc->sdc_state = SDCS_PREVRMB|SDCS_RSENSE; goto sdintr_rsense; } sdd->sdd_flags |= SDDF_INHRMV; if (sdc->sdc_state & SDCS_ECC) { sdc->sdc_state = SDCS_RETRY; goto sdintr_msel_reset; } sdc->sdc_state = SDCS_NORMAL; goto sdintr_exec; break; /****************************************/ /* */ /* REZERO done & RETRY COMMAND */ /* */ /****************************************/ case SDCS_ECC|SDCS_ECC_HOLD|SDCS_REZERO: if (sdc->sdc_firmware & SDCFW_DEFMODE) { sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD|SDCS_RETRY; goto sdintr_stst; } sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD; goto sdintr_msel_set; /********************************/ /* */ /* RETRY COMMAND */ /* */ /********************************/ case SDCS_RETRY: sdc->sdc_state = SDCS_NORMAL; goto sdintr_exec; /************************************************/ /* */ /* ERROR CORRECTION ON MODE SELECT result */ /* */ /************************************************/ case SDCS_ECC: if (tstatus != TGST_GOOD) { printf("sd%d: bad target status 0x%x\n", unit, sc->sc_tstatus); goto sdintr_error; }sdintr_ecc: if (bp->b_flags & B_READ) { sdc->sdc_state = SDCS_ECC|SDCS_RASREAD; im->im_tab.b_active = 2; scop_rdwr(intr, sc, slave, SCSI_INTEN, B_READ, sdwork, sdd->sdd_badsect, sdd->sdd_sectsize); return; } goto sdintr_rasblk; /************************************************/ /* */ /* READ DATA from BAD BLOCK result */ /* */ /************************************************/ case SDCS_ECC|SDCS_RASREAD: if (tstatus == TGST_CC) { sdc->sdc_state = SDCS_ECC|SDCS_RASREAD|SDCS_RSENSE; goto sdintr_rsense; } else if (tstatus != TGST_GOOD) { printf("sd%d: bad target status 0x%x\n", unit, sc->sc_tstatus); printf("sd%d: cannot read block\n", unit); goto sdintr_error; }sdintr_rasblk: if (sdd->sdd_flags & SDDF_WPROTECT) goto sdintr_error; sdc->sdc_state = SDCS_ECC|SDCS_RASBLK; im->im_tab.b_active = 2; scop_rasblk(intr, sc, slave, SCSI_INTEN, sdd->sdd_badsect); sdd->sdd_flags &= ~SDDF_VBADSECT; return; /****************************************/ /* */ /* REASSIGN BLOCK result */ /* */ /****************************************/ case SDCS_ECC|SDCS_RASBLK: if (tstatus == TGST_CC) { sdc->sdc_state = SDCS_ECC|SDCS_RASBLK|SDCS_RSENSE; goto sdintr_rsense; } else if (tstatus != TGST_GOOD) { printf("sd%d: bad target status 0x%x\n", unit, sc->sc_tstatus); goto sdintr_error; } printf("sd%d: block %d is reassigned\n", unit, sdd->sdd_badsect); if (bp->b_flags & B_READ) {sdintr_raswrite: sdc->sdc_state = SDCS_ECC|SDCS_RASWRITE; im->im_tab.b_active = 2; scop_rdwr(intr, sc, slave, SCSI_INTEN, B_WRITE, sdwork, sdd->sdd_badsect, sdd->sdd_sectsize); return; } sdc->sdc_state = SDCS_RETRY; goto sdintr_msel_reset; /************************************************/ /* */ /* WRITE DATA to REASSIGNED BLOCK result */ /* */ /************************************************/ case SDCS_ECC|SDCS_RASWRITE: if (tstatus == TGST_CC) { sdc->sdc_state = SDCS_ECC|SDCS_RASWRITE|SDCS_RSENSE; goto sdintr_rsense; } else if (tstatus != TGST_GOOD) { printf("sd%d: bad target status 0x%x\n", unit, sc->sc_tstatus); goto sdintr_error; } sdc->sdc_state = SDCS_RETRY; goto sdintr_msel_reset; /****************************************/ /* */ /* reset ECC & RETRY TIMES */ /* */ /****************************************/ case SDCS_ECCOFF|SDCS_RETRY: sdc->sdc_state = SDCS_RETRY; goto sdintr_msel_reset; /********************************************************/ /* */ /* READ DATA from BAD BLOCK result in faliure */ /* */ /********************************************************/ case SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA: if (tstatus == TGST_CC) { sdc->sdc_state = SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE; goto sdintr_rsense; } else if (tstatus != TGST_GOOD) { printf("sd%d: rasblk: bad target status 0x%x\n", unit, sc->sc_tstatus); goto sdintr_error; } bzero(sdwork, sdd->sdd_sectsize); scop_rdwr(intr, sc, slave, SCSI_INTDIS, B_WRITE, sdwork, sdd->sdd_badsect, sdd->sdd_sectsize); printf("sd%d: block %d is reassigned (lost data)\n", unit, sdd->sdd_badsect); goto sdintr_error; /****************************************/ /* */ /* issue START UNIT command */ /* */ /****************************************/ case SDCS_ECC|SDCS_ECC_HOLD: /* * Drive not ready... so start.. */ sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD|SDCS_RETRY;sdintr_stst: timeout(delay_start, (caddr_t)ii, hz); return; /****************************************/ /* */ /* RETRY with ECC & more RETRYS */ /* */ /****************************************/ case SDCS_ECC|SDCS_ECC_HOLD|SDCS_RETRY: sdc->sdc_state = SDCS_ECCOFF;sdintr_exec: if (sdc->sdc_countcc++ > MAXRETRYCNT) goto sdintr_error; sdexec(bp); return; /****************************************/ /* */ /* reset ECC & RETRY TIMES */ /* */ /****************************************/ case SDCS_ECCOFF: if (tstatus == TGST_CC) { sdc->sdc_state = SDCS_ECCOFF|SDCS_RSENSE; goto sdintr_rsense; } else if (tstatus != TGST_GOOD) { printf("sd%d: bad target status 0x%x\n", unit, sc->sc_tstatus); goto sdintr_error; } sdc->sdc_state = SDCS_NORMAL; goto sdintr_msel_reset;sdintr_msel_set: /* * set more ERROR RECOVERY PARAMETERS */ if ((erp_page = sdi->max_ERP_page) == NULL) goto check_target_status; bzero((caddr_t)sc->sc_param, 4); len = *(erp_page + 1) + 2; bcopy(erp_page, &sc->sc_param[4], len); im->im_tab.b_active = 2; scop_mselect(intr, sc, slave, SCSI_INTEN, (SDM_PF<<24) + len +4, (caddr_t)0); return;sdintr_msel_reset: if (sdc->sdc_firmware & SDCFW_DEFMODE) goto sdintr_exec; /* * set normal ERROR RECOVERY PARAMETERS */ erp_page = sdi->ERP_page; bzero((caddr_t)sc->sc_param, 4); len = *(erp_page + 1) + 2; bcopy(erp_page, &sc->sc_param[4], len); im->im_tab.b_active = 2; scop_mselect(intr, sc, slave, SCSI_INTEN, (SDM_PF<<24) + len +4, (caddr_t)0); return;sdintr_error: bp->b_flags |= B_ERROR; if (sdc->sdc_state & SDCS_ECC) { sdc->sdc_state = SDCS_NORMAL; goto sdintr_msel_reset; } break; /* * UNKNOWN STATUS */ default: printf("sd%d: unknown status (0x%x)\n", unit, sdc->sdc_state); goto sdintr_error; }sdintr_done: if (bp->b_flags & B_ERROR) { printf("%s%d%c: hard error sn%d ", "sd", minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno); printf("\n"); } sdd->sdd_lastblk = dkblock(bp) + btodb(bp->b_bcount - bp->b_resid); sdc->sdc_countcc = 0; sdc->sdc_retrycnt = 0; sdd->sdd_flags &= ~SDDF_VBADSECT; if (im->im_tab.b_active) { im->im_tab.b_active = 0; im->im_tab.b_errcnt = 0; im->im_tab.b_actf = 0; dp->b_active = 0; dp->b_errcnt = 0; dp->b_actf = bp->b_actf; if (bp == &csdbuf[unit]) { register struct scsi *ksc = &kernscsi[unit]; /* copy result */ bcopy((caddr_t)sc, (caddr_t)ksc, sizeof(struct scsi)); } iodone(bp); /* * If this unit has more work to do, *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -