dasd_eckd.c
来自「linux-2.4.29操作系统的源码」· C语言 代码 · 共 1,885 行 · 第 1/4 页
C
1,885 行
{ if (info->sid_data.cu_type == 0x3990 || info->sid_data.cu_type == 0x2105) if (info->sid_data.dev_type == 0x3390) return 0; if (info->sid_data.cu_type == 0x3990 || info->sid_data.cu_type == 0x2105) if (info->sid_data.dev_type == 0x3380) return 0; if (info->sid_data.cu_type == 0x9343) if (info->sid_data.dev_type == 0x9345) return 0; return -ENODEV;}static intdasd_eckd_check_characteristics (struct dasd_device_t *device){ int rc = 0; void *conf_data; void *rdc_data; int conf_len; dasd_eckd_private_t *private; if (device == NULL) { MESSAGE (KERN_WARNING, "%s", "Null device pointer passed to characteristics " "checker"); return -ENODEV; } device->private = kmalloc (sizeof (dasd_eckd_private_t), GFP_KERNEL); if (device->private == NULL) { MESSAGE (KERN_WARNING, "%s", "memory allocation failed for private data"); rc = -ENOMEM; goto fail; } private = (dasd_eckd_private_t *) device->private; rdc_data = (void *) &(private->rdc_data); /* Read Device Characteristics */ rc = read_dev_chars (device->devinfo.irq, &rdc_data, 64); if (rc) { MESSAGE (KERN_WARNING, "Read device characteristics returned error %d", rc); goto fail; } DEV_MESSAGE (KERN_INFO, device, "%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d", private->rdc_data.dev_type, private->rdc_data.dev_model, private->rdc_data.cu_type, private->rdc_data.cu_model.model, private->rdc_data.no_cyl, private->rdc_data.trk_per_cyl, private->rdc_data.sec_per_trk); /* set default cache operations */ private->attrib.operation = DASD_NORMAL_CACHE; private->attrib.nr_cyl = 0; /* Read Configuration Data */ rc = read_conf_data (device->devinfo.irq, &conf_data, &conf_len, LPM_ANYPATH); if (rc == -EOPNOTSUPP) { rc = 0; /* this one is ok */ } if (rc) { MESSAGE (KERN_WARNING, "Read configuration data returned error %d", rc); goto fail; } if (conf_data == NULL) { MESSAGE (KERN_WARNING, "%s", "No configuration data retrieved"); goto out; /* no errror */ } if (conf_len != sizeof (dasd_eckd_confdata_t)) { MESSAGE (KERN_WARNING, "sizes of configuration data mismatch" "%d (read) vs %ld (expected)", conf_len, sizeof (dasd_eckd_confdata_t)); goto out; /* no errror */ } memcpy (&private->conf_data, conf_data, sizeof (dasd_eckd_confdata_t)); DEV_MESSAGE (KERN_INFO, device, "%04X/%02X(CU:%04X/%02X): Configuration data read", private->rdc_data.dev_type, private->rdc_data.dev_model, private->rdc_data.cu_type, private->rdc_data.cu_model.model); goto out; fail: if (device->private) { kfree (device->private); device->private = NULL; } out: return rc;}static inline intdasd_eckd_cdl_reclen (dasd_device_t * device, int recid){ 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); if (recid < 3) return sizes_trk0[recid]; if (recid < blk_per_trk) return byt_per_blk; if (recid < 2 * blk_per_trk) return LABEL_SIZE; return byt_per_blk;}static ccw_req_t *dasd_eckd_init_analysis (struct dasd_device_t *device){ ccw_req_t *cqr = NULL; ccw1_t *ccw; DE_eckd_data_t *DE_data; LO_eckd_data_t *LO_data; dasd_eckd_private_t *private = (dasd_eckd_private_t *)device->private; 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) { MESSAGE (KERN_WARNING, "%s", "No memory to allocate initialization request"); 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->buildclk = get_clock (); cqr->status = CQR_STATUS_FILLED; dasd_chanq_enq (&device->queue, cqr); goto out; clear_cqr: dasd_free_request (cqr,device); MESSAGE (KERN_WARNING, "%s", "No memory to allocate initialization request"); 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 ) { DEV_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) { DEV_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) { DEV_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" : "linux disk layout"; DEV_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)){ DEV_MESSAGE (KERN_INFO, device, "Track no %d too big!", fdata->start_unit); return NULL; } if ( fdata->start_unit > fdata->stop_unit) { DEV_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: MESSAGE (KERN_WARNING, "Invalid blocksize %d...terminating!", 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: MESSAGE (KERN_WARNING, "Invalid flags 0x%x...terminating!", 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))) { DBF_DEV_EVENT (DBF_NOTICE, 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); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?