📄 dasd_eckd.c
字号:
eckd_count_t *count_data = private->count_area; cqr = dasd_alloc_request (dasd_eckd_discipline.name, 8 + 1, sizeof (DE_eckd_data_t) + 2 * sizeof (LO_eckd_data_t), device); if (cqr == NULL) { printk (KERN_WARNING PRINTK_HEADER "No memory to allocate initialization request\n"); goto out; } DE_data = cqr->data; LO_data = cqr->data + sizeof (DE_eckd_data_t); ccw = cqr->cpaddr; if (define_extent (ccw, DE_data, 0, 2, DASD_ECKD_CCW_READ_COUNT, device, cqr)) { goto clear_cqr; } ccw->flags |= CCW_FLAG_CC; ccw++; if (locate_record (ccw, LO_data++, 0, 0, 4, DASD_ECKD_CCW_READ_COUNT, device, 0, cqr)) { goto clear_cqr; } ccw->flags |= CCW_FLAG_CC; ccw++; ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT; ccw->count = 8; if (dasd_set_normalized_cda (ccw, __pa (count_data++), cqr, device)) { goto clear_cqr; } ccw->flags |= CCW_FLAG_CC; ccw++; ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT; ccw->count = 8; if (dasd_set_normalized_cda (ccw, __pa (count_data++), cqr, device)) { goto clear_cqr; } ccw->flags |= CCW_FLAG_CC; ccw++; ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT; ccw->count = 8; if (dasd_set_normalized_cda (ccw, __pa (count_data++), cqr, device)) { goto clear_cqr; } ccw->flags |= CCW_FLAG_CC; ccw++; ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT; ccw->count = 8; if (dasd_set_normalized_cda (ccw, __pa (count_data++), cqr, device)) { goto clear_cqr; } ccw->flags |= CCW_FLAG_CC; ccw++; if (locate_record (ccw, LO_data++, 2, 0, 1, DASD_ECKD_CCW_READ_COUNT, device, 0, cqr)) { goto clear_cqr; } ccw->flags |= CCW_FLAG_CC; ccw++; ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT; ccw->count = 8; if (dasd_set_normalized_cda (ccw, __pa (count_data), cqr, device)) { goto clear_cqr; } cqr->device = device; cqr->retries = 0; cqr->status = CQR_STATUS_FILLED; dasd_chanq_enq (&device->queue, cqr); goto out; clear_cqr: dasd_free_request (cqr,device); printk (KERN_WARNING PRINTK_HEADER "No memory to allocate initialization request\n"); cqr=NULL; out: return cqr;}static intdasd_eckd_do_analysis (struct dasd_device_t *device){ int sb, rpt; dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private; eckd_count_t *count_area = NULL; char *cdl_msg; int status; int i; private->uses_cdl = 1; status = device->init_cqr->status; dasd_chanq_deq (&device->queue, device->init_cqr); dasd_free_request (device->init_cqr, device); /* Free the cqr and cleanup device->sizes */ if ( status != CQR_STATUS_DONE ) { DASD_MESSAGE (KERN_WARNING,device,"%s", "volume analysis returned unformatted disk"); return -EMEDIUMTYPE; } /* Check Track 0 for Compatible Disk Layout */ for (i = 0; i < 3; i++) { if ((i < 3) && ((private->count_area[i].kl != 4) || (private->count_area[i].dl != dasd_eckd_cdl_reclen (device, i) - 4))) { private->uses_cdl = 0; break; } } if (i == 3) { count_area = &private->count_area[4]; } if (private->uses_cdl == 0) { for (i = 0; i < 5; i++) { if ((private->count_area[i].kl != 0) || (private->count_area[i].dl != private->count_area[0].dl)) { break; } } if (i == 5) { count_area = &private->count_area[0]; } } else { if (private->count_area[3].record == 1) { DASD_MESSAGE (KERN_WARNING, device, "%s", "Trk 0: no records after VTOC!"); } } if (count_area != NULL && /* we found notthing violating our disk layout */ count_area->kl == 0) { /* find out blocksize */ switch (count_area->dl) { case 512: case 1024: case 2048: case 4096: device->sizes.bp_block = count_area->dl; break; } } if (device->sizes.bp_block == 0) { DASD_MESSAGE (KERN_WARNING, device, "%s", "Volume has incompatible disk layout"); return -EMEDIUMTYPE; } device->sizes.s2b_shift = 0; /* bits to shift 512 to get a block */ device->sizes.pt_block = 2; for (sb = 512; sb < device->sizes.bp_block; sb = sb << 1) device->sizes.s2b_shift++; rpt = recs_per_track (&private->rdc_data, 0, device->sizes.bp_block); device->sizes.blocks = (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl * recs_per_track (&private->rdc_data, 0, device->sizes.bp_block)); cdl_msg = private-> uses_cdl ? "compatible disk layout" : "classic disk layout"; DASD_MESSAGE (KERN_INFO, device, "(%dkB blks): %dkB at %dkB/trk %s", (device->sizes.bp_block >> 10), (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl * recs_per_track (&private->rdc_data, 0, device->sizes.bp_block) * (device->sizes.bp_block >> 9)) >> 1, (recs_per_track (&private->rdc_data, 0, device->sizes.bp_block) * device->sizes.bp_block) >> 10, cdl_msg); return 0;}static intdasd_eckd_fill_geometry (struct dasd_device_t *device, struct hd_geometry *geo){ int rc = 0; dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private; switch (device->sizes.bp_block) { case 512: case 1024: case 2048: case 4096: geo->sectors = recs_per_track (&(private->rdc_data), 0, device->sizes.bp_block); break; default: break; } geo->cylinders = private->rdc_data.no_cyl; geo->heads = private->rdc_data.trk_per_cyl; return rc;}static ccw_req_t *dasd_eckd_format_device (dasd_device_t * device, format_data_t * fdata){ int i; ccw_req_t *fcp = NULL; DE_eckd_data_t *DE_data = NULL; LO_eckd_data_t *LO_data = NULL; eckd_count_t *ct_data = NULL; eckd_count_t *r0_data = NULL; eckd_home_t *ha_data = NULL; ccw1_t *last_ccw = NULL; void *last_data = NULL; dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private; int rpt = recs_per_track (&(private->rdc_data), 0, fdata->blksize); int cyl = fdata->start_unit / private->rdc_data.trk_per_cyl; int head = fdata->start_unit % private->rdc_data.trk_per_cyl; int wrccws = rpt; int datasize = sizeof (DE_eckd_data_t) + sizeof (LO_eckd_data_t); if (fdata->start_unit >= (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl)){ DASD_MESSAGE (KERN_INFO, device, "Track no %d too big!", fdata->start_unit); return NULL; } if ( fdata->start_unit > fdata->stop_unit) { DASD_MESSAGE (KERN_INFO, device, "Track %d reached! ending.", fdata->start_unit); return NULL; } switch (fdata->blksize) { case 512: case 1024: case 2048: case 4096: break; default: printk (KERN_WARNING PRINTK_HEADER "Invalid blocksize %d...terminating!\n", fdata->blksize); return NULL; } switch (fdata->intensity) { case 0x00: case 0x01: case 0x03: case 0x04: /* make track invalid */ case 0x08: case 0x09: case 0x0b: case 0x0c: break; default: printk (KERN_WARNING PRINTK_HEADER "Invalid flags 0x%x...terminating!\n", fdata->intensity); return NULL; } /* print status line */ if ((private->rdc_data.no_cyl < 20) ? (fdata->start_unit % private->rdc_data.no_cyl == 0) : (fdata->start_unit % private->rdc_data.no_cyl == 0 && (fdata->start_unit / private->rdc_data.no_cyl) % (private->rdc_data.no_cyl / 20))) { DASD_MESSAGE (KERN_INFO, device, "Format Cylinder: %d Flags: %d", fdata->start_unit / private->rdc_data.trk_per_cyl, fdata->intensity); } if ((fdata->intensity & ~0x8) & 0x04) { wrccws = 1; rpt = 1; } else { if (fdata->intensity & 0x1) { wrccws++; datasize += sizeof (eckd_count_t); } if (fdata->intensity & 0x2) { wrccws++; datasize += sizeof (eckd_home_t); } } fcp = dasd_alloc_request (dasd_eckd_discipline.name, wrccws + 2 + 1, datasize + rpt * sizeof (eckd_count_t), device ); if (fcp != NULL) { fcp->device = device; fcp->retries = 2; /* set retry counter to enable ERP */ last_data = fcp->data; DE_data = (DE_eckd_data_t *) last_data; last_data = (void *) (DE_data + 1); LO_data = (LO_eckd_data_t *) last_data; last_data = (void *) (LO_data + 1); if (fdata->intensity & 0x2) { ha_data = (eckd_home_t *) last_data; last_data = (void *) (ha_data + 1); } if (fdata->intensity & 0x1) { r0_data = (eckd_count_t *) last_data; last_data = (void *) (r0_data + 1); } ct_data = (eckd_count_t *) last_data; last_ccw = fcp->cpaddr; switch (fdata->intensity & ~0x08) { case 0x03: if (define_extent (last_ccw, DE_data, fdata->start_unit, fdata->start_unit, DASD_ECKD_CCW_WRITE_HOME_ADDRESS, device, fcp)) { goto clear_fcp; } last_ccw->flags |= CCW_FLAG_CC; last_ccw++; if (locate_record (last_ccw, LO_data, fdata->start_unit, 0, wrccws, DASD_ECKD_CCW_WRITE_HOME_ADDRESS, device, device->sizes.bp_block, fcp)) { goto clear_fcp; } last_ccw->flags |= CCW_FLAG_CC; last_ccw++; break; case 0x01: if (define_extent (last_ccw, DE_data, fdata->start_unit, fdata->start_unit, DASD_ECKD_CCW_WRITE_RECORD_ZERO, device, fcp)) { goto clear_fcp; } last_ccw->flags |= CCW_FLAG_CC; last_ccw++; if (locate_record (last_ccw, LO_data, fdata->start_unit, 0, wrccws, DASD_ECKD_CCW_WRITE_RECORD_ZERO, device, device->sizes.bp_block, fcp)) { goto clear_fcp; } last_ccw->flags |= CCW_FLAG_CC; last_ccw++; memset (r0_data, 0, sizeof (eckd_count_t)); break; case 0x04: fdata->blksize = 8; case 0x00: if (define_extent (last_ccw, DE_data, fdata->start_unit, fdata->start_unit, DASD_ECKD_CCW_WRITE_CKD, device, fcp)) { dasd_free_request (fcp, device); return NULL; } last_ccw->flags |= CCW_FLAG_CC; last_ccw++; if (locate_record (last_ccw, LO_data, fdata->start_unit, 0, wrccws, DASD_ECKD_CCW_WRITE_CKD, device, fdata->blksize, fcp)) { goto clear_fcp; } last_ccw->flags |= CCW_FLAG_CC; last_ccw++; break; default: PRINT_WARN ("Unknown format flags...%d\n", fdata->intensity); return NULL; } if (fdata->intensity & 0x02) { PRINT_WARN ("Unsupported format flag...%d\n", fdata->intensity); return NULL; } if (fdata->intensity & 0x01) { /* write record zero */ r0_data->cyl = cyl; r0_data->head = head; r0_data->record = 0; r0_data->kl = 0; r0_data->dl = 8; last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_RECORD_ZERO; last_ccw->count = 8; last_ccw->flags |= CCW_FLAG_CC | CCW_FLAG_SLI; if (dasd_set_normalized_cda (last_ccw, __pa (r0_data), fcp, device)) { goto clear_fcp; } last_ccw++; } if ((fdata->intensity & ~0x08) & 0x04) { /* erase track */ memset (ct_data, 0, sizeof (eckd_count_t)); ct_data->cyl = cyl; ct_data->head = head; ct_data->record = 1; ct_data->kl = 0; ct_data->dl = 0; last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD; last_ccw->count = 8; last_ccw->flags |= CCW_FLAG_CC | CCW_FLAG_SLI; if (dasd_set_normalized_cda (last_ccw, __pa (ct_data), fcp, device)) { goto clear_fcp; } last_ccw++; } else { /* write remaining records */ for (i = 0; i < rpt; i++) { memset (ct_data + i, 0, sizeof (eckd_count_t)); (ct_data + i)->cyl = cyl; (ct_data + i)->head = head; (ct_data + i)->record = i + 1; (ct_data + i)->kl = 0; if (fdata->intensity & 0x08) { // special handling when formatting CDL switch (fdata->start_unit) { case 0: if (i < 3) { (ct_data + i)->kl = 4; (ct_data + i)->dl = sizes_trk0[i] - 4; } else (ct_data + i)->dl = fdata->blksize; break; case 1: (ct_data + i)->kl = 44; (ct_data + i)->dl = LABEL_SIZE - 44; break; default: (ct_data + i)->dl = fdata->blksize; break; } } else (ct_data + i)->dl = fdata->blksize; last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD; last_ccw->flags |= CCW_FLAG_CC | CCW_FLAG_SLI; last_ccw->count = 8; if (dasd_set_normalized_cda (last_ccw, __pa (ct_data + i), fcp, device)) { goto clear_fcp; } last_ccw++; } } (last_ccw - 1)->flags &= ~(CCW_FLAG_CC | CCW_FLAG_DC); fcp->device = device; fcp->status = CQR_STATUS_FILLED; } goto out; clear_fcp: dasd_free_request (fcp, device); fcp=NULL; out: return fcp;}static dasd_era_tdasd_eckd_examine_error (ccw_req_t * cqr, devstat_t * stat){ dasd_device_t *device = (dasd_device_t *) cqr->device; if (stat->cstat == 0x00 && stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END)) return dasd_era_none; switch (device->devinfo.sid_data.cu_type) { case 0x3990: case 0x2105: return dasd_3990_erp_examine (cqr, stat); case 0x9343: return dasd_9343_erp_examine (cqr, stat); default: printk (KERN_WARNING PRINTK_HEADER "default (unknown CU type) - RECOVERABLE return \n"); return dasd_era_recover; }}static dasd_erp_action_fn_tdasd_eckd_erp_action (ccw_req_t * cqr){ dasd_device_t *device = (dasd_device_t *) cqr->device; switch (device->devinfo.sid_data.cu_type) { case 0x3990: case 0x2105: return dasd_3990_erp_action; case 0x9343: /* Return dasd_9343_erp_action; */ default: return dasd_default_erp_action; }}static dasd_erp_postaction_fn_tdasd_eckd_erp_postaction (ccw_req_t * cqr){ return dasd_default_erp_postaction;}inline unsigned chardasd_eckd_cdl_cmd (dasd_device_t * device, int recid, int cmd){ dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private; int byt_per_blk = device->sizes.bp_block; int blk_per_trk = recs_per_track (&(private->rdc_data), 0, byt_per_blk); switch (cmd) { case READ: if (recid < 3) return DASD_ECKD_CCW_READ_KD_MT; if (recid < blk_per_trk) return DASD_ECKD_CCW_READ_MT; if (recid < 2 * blk_per_trk) return DASD_ECKD_CCW_READ_KD_MT; return DASD_ECKD_CCW_READ_MT; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -