📄 dasd_3990_erp.c
字号:
/* 'Data Check' */ if ((erp_filled == NULL) && (sense[0] & SNS0_DATA_CHECK)) { erp_filled = dasd_3990_erp_data_check(erp, sense); } /* 'Overrun' */ if ((erp_filled == NULL) && (sense[0] & SNS0_OVERRUN)) { erp_filled = dasd_3990_erp_overrun(erp, sense); } /* 'Invalid Track Format' */ if ((erp_filled == NULL) && (sense[1] & SNS1_INV_TRACK_FORMAT)) { erp_filled = dasd_3990_erp_inv_format(erp, sense); } /* 'End-of-Cylinder' */ if ((erp_filled == NULL) && (sense[1] & SNS1_EOC)) { erp_filled = dasd_3990_erp_EOC(erp, sense); } /* 'Environmental Data' */ if ((erp_filled == NULL) && (sense[2] & SNS2_ENV_DATA_PRESENT)) { erp_filled = dasd_3990_erp_env_data(erp, sense); } /* 'No Record Found' */ if ((erp_filled == NULL) && (sense[1] & SNS1_NO_REC_FOUND)) { erp_filled = dasd_3990_erp_no_rec(erp, sense); } /* 'File Protected' */ if ((erp_filled == NULL) && (sense[1] & SNS1_FILE_PROTECTED)) { erp_filled = dasd_3990_erp_file_prot(erp); } /* other (unknown) error - do default ERP */ if (erp_filled == NULL) { erp_filled = erp; } return erp_filled;} /* END dasd_3990_erp_inspect_24 *//* ***************************************************************************** * 32 byte sense ERP functions (only) ***************************************************************************** *//* * DASD_3990_ERPACTION_10_32 * * DESCRIPTION * Handles 32 byte 'Action 10' of Single Program Action Codes. * Just retry and if retry doesn't work, return with error. * * PARAMETER * erp current erp_head * sense current sense data * RETURN VALUES * erp modified erp_head */static struct dasd_ccw_req *dasd_3990_erp_action_10_32(struct dasd_ccw_req * erp, char *sense){ struct dasd_device *device = erp->device; erp->retries = 256; erp->function = dasd_3990_erp_action_10_32; DEV_MESSAGE(KERN_DEBUG, device, "%s", "Perform logging requested"); return erp;} /* end dasd_3990_erp_action_10_32 *//* * DASD_3990_ERP_ACTION_1B_32 * * DESCRIPTION * Handles 32 byte 'Action 1B' of Single Program Action Codes. * A write operation could not be finished because of an unexpected * condition. * The already created 'default erp' is used to get the link to * the erp chain, but it can not be used for this recovery * action because it contains no DE/LO data space. * * PARAMETER * default_erp already added default erp. * sense current sense data * * RETURN VALUES * erp new erp or * default_erp in case of imprecise ending or error */static struct dasd_ccw_req *dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense){ struct dasd_device *device = default_erp->device; __u32 cpa = 0; struct dasd_ccw_req *cqr; struct dasd_ccw_req *erp; struct DE_eckd_data *DE_data; char *LO_data; /* LO_eckd_data_t */ struct ccw1 *ccw; DEV_MESSAGE(KERN_DEBUG, device, "%s", "Write not finished because of unexpected condition"); default_erp->function = dasd_3990_erp_action_1B_32; /* determine the original cqr */ cqr = default_erp; while (cqr->refers != NULL) { cqr = cqr->refers; } /* for imprecise ending just do default erp */ if (sense[1] & 0x01) { DEV_MESSAGE(KERN_DEBUG, device, "%s", "Imprecise ending is set - just retry"); return default_erp; } /* determine the address of the CCW to be restarted */ /* Imprecise ending is not set -> addr from IRB-SCSW */ cpa = default_erp->refers->irb.scsw.cpa; if (cpa == 0) { DEV_MESSAGE(KERN_DEBUG, device, "%s", "Unable to determine address of the CCW " "to be restarted"); return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); } /* Build new ERP request including DE/LO */ erp = dasd_alloc_erp_request((char *) &cqr->magic, 2 + 1,/* DE/LO + TIC */ sizeof (struct DE_eckd_data) + sizeof (struct LO_eckd_data), device); if (IS_ERR(erp)) { DEV_MESSAGE(KERN_ERR, device, "%s", "Unable to allocate ERP"); return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); } /* use original DE */ DE_data = erp->data; memcpy(DE_data, cqr->data, sizeof (struct DE_eckd_data)); /* create LO */ LO_data = erp->data + sizeof (struct DE_eckd_data); if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) { DEV_MESSAGE(KERN_ERR, device, "%s", "BUG - this should not happen"); return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); } if ((sense[7] & 0x3F) == 0x01) { /* operation code is WRITE DATA -> data area orientation */ LO_data[0] = 0x81; } else if ((sense[7] & 0x3F) == 0x03) { /* operation code is FORMAT WRITE -> index orientation */ LO_data[0] = 0xC3; } else { LO_data[0] = sense[7]; /* operation */ } LO_data[1] = sense[8]; /* auxiliary */ LO_data[2] = sense[9]; LO_data[3] = sense[3]; /* count */ LO_data[4] = sense[29]; /* seek_addr.cyl */ LO_data[5] = sense[30]; /* seek_addr.cyl 2nd byte */ LO_data[7] = sense[31]; /* seek_addr.head 2nd byte */ memcpy(&(LO_data[8]), &(sense[11]), 8); /* create DE ccw */ ccw = erp->cpaddr; memset(ccw, 0, sizeof (struct ccw1)); ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT; ccw->flags = CCW_FLAG_CC; ccw->count = 16; ccw->cda = (__u32)(addr_t) DE_data; /* create LO ccw */ ccw++; memset(ccw, 0, sizeof (struct ccw1)); ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD; ccw->flags = CCW_FLAG_CC; ccw->count = 16; ccw->cda = (__u32)(addr_t) LO_data; /* TIC to the failed ccw */ ccw++; ccw->cmd_code = CCW_CMD_TIC; ccw->cda = cpa; /* fill erp related fields */ erp->function = dasd_3990_erp_action_1B_32; erp->refers = default_erp->refers; erp->device = device; erp->magic = default_erp->magic; erp->expires = 0; erp->retries = 256; erp->buildclk = get_clock(); erp->status = DASD_CQR_FILLED; /* remove the default erp */ dasd_free_erp_request(default_erp, device); return erp;} /* end dasd_3990_erp_action_1B_32 *//* * DASD_3990_UPDATE_1B * * DESCRIPTION * Handles the update to the 32 byte 'Action 1B' of Single Program * Action Codes in case the first action was not successful. * The already created 'previous_erp' is the currently not successful * ERP. * * PARAMETER * previous_erp already created previous erp. * sense current sense data * RETURN VALUES * erp modified erp */static struct dasd_ccw_req *dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense){ struct dasd_device *device = previous_erp->device; __u32 cpa = 0; struct dasd_ccw_req *cqr; struct dasd_ccw_req *erp; char *LO_data; /* struct LO_eckd_data */ struct ccw1 *ccw; DEV_MESSAGE(KERN_DEBUG, device, "%s", "Write not finished because of unexpected condition" " - follow on"); /* determine the original cqr */ cqr = previous_erp; while (cqr->refers != NULL) { cqr = cqr->refers; } /* for imprecise ending just do default erp */ if (sense[1] & 0x01) { DEV_MESSAGE(KERN_DEBUG, device, "%s", "Imprecise ending is set - just retry"); previous_erp->status = DASD_CQR_QUEUED; return previous_erp; } /* determine the address of the CCW to be restarted */ /* Imprecise ending is not set -> addr from IRB-SCSW */ cpa = previous_erp->irb.scsw.cpa; if (cpa == 0) { DEV_MESSAGE(KERN_DEBUG, device, "%s", "Unable to determine address of the CCW " "to be restarted"); previous_erp->status = DASD_CQR_FAILED; return previous_erp; } erp = previous_erp; /* update the LO with the new returned sense data */ LO_data = erp->data + sizeof (struct DE_eckd_data); if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) { DEV_MESSAGE(KERN_ERR, device, "%s", "BUG - this should not happen"); previous_erp->status = DASD_CQR_FAILED; return previous_erp; } if ((sense[7] & 0x3F) == 0x01) { /* operation code is WRITE DATA -> data area orientation */ LO_data[0] = 0x81; } else if ((sense[7] & 0x3F) == 0x03) { /* operation code is FORMAT WRITE -> index orientation */ LO_data[0] = 0xC3; } else { LO_data[0] = sense[7]; /* operation */ } LO_data[1] = sense[8]; /* auxiliary */ LO_data[2] = sense[9]; LO_data[3] = sense[3]; /* count */ LO_data[4] = sense[29]; /* seek_addr.cyl */ LO_data[5] = sense[30]; /* seek_addr.cyl 2nd byte */ LO_data[7] = sense[31]; /* seek_addr.head 2nd byte */ memcpy(&(LO_data[8]), &(sense[11]), 8); /* TIC to the failed ccw */ ccw = erp->cpaddr; /* addr of DE ccw */ ccw++; /* addr of LE ccw */ ccw++; /* addr of TIC ccw */ ccw->cda = cpa; erp->status = DASD_CQR_QUEUED; return erp;} /* end dasd_3990_update_1B *//* * DASD_3990_ERP_COMPOUND_RETRY * * DESCRIPTION * Handles the compound ERP action retry code. * NOTE: At least one retry is done even if zero is specified * by the sense data. This makes enqueueing of the request * easier. * * PARAMETER * sense sense data of the actual error * erp pointer to the currently created ERP * * RETURN VALUES * erp modified ERP pointer * */static voiddasd_3990_erp_compound_retry(struct dasd_ccw_req * erp, char *sense){ switch (sense[25] & 0x03) { case 0x00: /* no not retry */ erp->retries = 1; break; case 0x01: /* retry 2 times */ erp->retries = 2; break; case 0x02: /* retry 10 times */ erp->retries = 10; break; case 0x03: /* retry 256 times */ erp->retries = 256; break; default: BUG(); } erp->function = dasd_3990_erp_compound_retry;} /* end dasd_3990_erp_compound_retry *//* * DASD_3990_ERP_COMPOUND_PATH * * DESCRIPTION * Handles the compound ERP action for retry on alternate * channel path. * * PARAMETER * sense sense data of the actual error * erp pointer to the currently created ERP * * RETURN VALUES * erp modified ERP pointer * */static voiddasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense){ if (sense[25] & DASD_SENSE_BIT_3) { dasd_3990_erp_alternate_path(erp); if (erp->status == DASD_CQR_FAILED) { /* reset the lpm and the status to be able to * try further actions. */ erp->lpm = 0; erp->status = DASD_CQR_ERROR; } } erp->function = dasd_3990_erp_compound_path;} /* end dasd_3990_erp_compound_path *//* * DASD_3990_ERP_COMPOUND_CODE * * DESCRIPTION * Handles the compound ERP action for retry code. * * PARAMETER * sense sense data of the actual error * erp pointer to the currently created ERP * * RETURN VALUES * erp NEW ERP pointer * */static struct dasd_ccw_req *dasd_3990_erp_compound_code(struct dasd_ccw_req * erp, char *sense){ if (sense[25] & DASD_SENSE_BIT_2) { switch (sense[28]) { case 0x17: /* issue a Diagnostic Control command with an * Inhibit Write subcommand and controler modifier */ erp = dasd_3990_erp_DCTL(erp, 0x20); break; case 0x25: /* wait for 5 seconds and retry again */ erp->retries = 1; dasd_3990_erp_block_queue (erp, 5*HZ); break; default: /* should not happen - continue */ break; } } erp->function = dasd_3990_erp_compound_code; return erp;} /* end dasd_3990_erp_compound_code *//* * DASD_3990_ERP_COMPOUND_CONFIG * * DESCRIPTION * Handles the compound ERP action for configruation * dependent error. * Note: duplex handling is not implemented (yet). * * PARAMETER * sense sense data of the actual error * erp pointer to the currently created ERP * * RETURN VALUES * erp modified ERP pointer * */static voiddasd_3990_erp_compound_config(struct dasd_ccw_req * erp, char *sense){ if ((sense[25] & DASD_SENSE_BIT_1) && (sense[26] & DASD_SENSE_BIT_2)) { /* set to suspended duplex state then restart */ struct dasd_device *device = erp->device; DEV_MESSAGE(KERN_ERR, device, "%s", "Set device to suspended duplex state should be " "done!\n" "This is not implemented yet (for compound ERP)" " - please report to linux390@de.ibm.com"); } erp->function = dasd_3990_erp_compound_config;} /* end dasd_3990_erp_compound_config *//* * DASD_3990_ERP_COMPOUND * * DESCRIPTION * Does the further compound program action if * compound retry was not successful. * * PARAMETER * sense sense data of the actual error * erp pointer to the current (failed) ERP * * RETURN VALUES * erp (additional) ERP pointer * */static struct dasd_ccw_req *dasd_3990_erp_compound(struct dasd_ccw_req * erp, char *sense){ if ((erp->function == dasd_3990_erp_compound_retry) && (erp->status == DASD_CQR_ERROR)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -