dasd_diag.c
来自「linux-2.4.29操作系统的源码」· C语言 代码 · 共 624 行 · 第 1/2 页
C
624 行
DBF_EVENT (DBF_INFO, "%04X: %04X on real %04X/%02X", rdc_data->vrdcdvno, rdc_data->vrdcvtyp, rdc_data->vrdccrty, rdc_data->vrdccrmd); /* Figure out position of label block */ if (private->rdc_data.vrdcvcla == DEV_CLASS_FBA) { device->sizes.pt_block = 1; } else if (private->rdc_data.vrdcvcla == DEV_CLASS_ECKD || private->rdc_data.vrdcvcla == DEV_CLASS_CKD) { device->sizes.pt_block = 2; } else { BUG(); } label = (unsigned long *) get_free_page (GFP_KERNEL); if (!label) { MESSAGE (KERN_WARNING, "%s", "No memory to allocate label struct"); rc = -ENOMEM; goto fail; } mdsk_term_io (device); /* first terminate all outstanding operations */ /* figure out blocksize of device */ for (bsize = 512; bsize <= PAGE_SIZE; bsize <<= 1) { diag_bio_t *bio; diag_rw_io_t *iob = &private->iob; rc = mdsk_init_io (device, bsize, 0, 64); if (rc > 4) { continue; } cqr = dasd_alloc_request (dasd_diag_discipline.name, sizeof (diag_bio_t) / sizeof (ccw1_t), 0, device); if (cqr == NULL) { MESSAGE (KERN_WARNING, "%s", "No memory to allocate initialization request"); rc = -ENOMEM; goto fail; } bio = (diag_bio_t *) (cqr->cpaddr); memset (bio, 0, sizeof (diag_bio_t)); bio->type = MDSK_READ_REQ; bio->block_number = device->sizes.pt_block + 1; bio->buffer = __pa (label); cqr->device = device; cqr->status = CQR_STATUS_FILLED; memset (iob, 0, sizeof (diag_rw_io_t)); iob->dev_nr = rdc_data->vrdcdvno; iob->block_count = 1; iob->interrupt_params = (u32)(addr_t) cqr; iob->bio_list = __pa (bio); rc = dia250 (iob, RW_BIO); dasd_free_request(cqr, device); if (rc == 0) { if (label[3] != bsize || label[0] != 0xc3d4e2f1 || /* != CMS1 */ label[13] == 0 ){ rc = -EMEDIUMTYPE; goto fail; } break; } mdsk_term_io (device); } if (bsize > PAGE_SIZE) { rc = -EMEDIUMTYPE; goto fail; } device->sizes.blocks = label[7]; device->sizes.bp_block = bsize; device->sizes.s2b_shift = 0; /* bits to shift 512 to get a block */ for (sb = 512; sb < bsize; sb = sb << 1) device->sizes.s2b_shift++; DEV_MESSAGE (KERN_INFO, device, "capacity (%dkB blks): %ldkB", (device->sizes.bp_block >> 10), (device->sizes.blocks << device->sizes.s2b_shift) >> 1); rc = 0; goto out; fail: if (device->private) { kfree (device->private); device->private = NULL; } out: if (label) { free_page ((unsigned long) label); } return rc;}static intdasd_diag_fill_geometry (struct dasd_device_t *device, struct hd_geometry *geo){ int rc = 0; unsigned long sectors = device->sizes.blocks << device->sizes.s2b_shift; unsigned long tracks = sectors >> 6; unsigned long cyls = tracks >> 4; switch (device->sizes.bp_block) { case 512: case 1024: case 2048: case 4096: break; default: return -EINVAL; } geo->cylinders = cyls; geo->heads = 16; geo->sectors = 128 >> device->sizes.s2b_shift; return rc;}static dasd_era_tdasd_diag_examine_error (ccw_req_t * cqr, devstat_t * stat){ return dasd_era_fatal;}static ccw_req_t *dasd_diag_build_cp_from_req (dasd_device_t * device, struct request *req){ ccw_req_t *rw_cp = NULL; struct buffer_head *bh; int rw_cmd; int noblk = req->nr_sectors >> device->sizes.s2b_shift; int byt_per_blk = device->sizes.bp_block; int block; diag_bio_t *bio; int bhct; long size; unsigned long reloc_sector = req->sector + device->major_info->gendisk.part[MINOR (req->rq_dev)].start_sect; if (!noblk) { MESSAGE (KERN_ERR, "%s", "No blocks to read/write...returning"); return ERR_PTR(-EINVAL); } if (req->cmd == READ) { rw_cmd = MDSK_READ_REQ; } else { rw_cmd = MDSK_WRITE_REQ; } bhct = 0; for (bh = req->bh; bh; bh = bh->b_reqnext) { if (bh->b_size < byt_per_blk) BUG(); bhct += bh->b_size >> (device->sizes.s2b_shift+9); } /* Build the request */ rw_cp = dasd_alloc_request (dasd_diag_discipline.name, bhct << 1, 0, device); if (!rw_cp) { return ERR_PTR(-ENOMEM); } bio = (diag_bio_t *) (rw_cp->cpaddr); block = reloc_sector >> device->sizes.s2b_shift; for (bh = req->bh; bh; bh = bh->b_reqnext) { memset (bio, 0, sizeof (diag_bio_t)); for (size = 0; size < bh->b_size; size += byt_per_blk) { bio->type = rw_cmd; bio->block_number = block + 1; bio->buffer = __pa (bh->b_data + size); bio++; block++; } } rw_cp->buildclk = get_clock (); rw_cp->device = device; rw_cp->expires = 50 * TOD_SEC; /* 50 seconds */ rw_cp->req = req; check_then_set (&rw_cp->status, CQR_STATUS_EMPTY, CQR_STATUS_FILLED); return rw_cp;}static intdasd_diag_fill_info (dasd_device_t * device, dasd_information2_t * info){ int rc = 0; info->FBA_layout = 1; info->format = DASD_FORMAT_LDL; info->characteristics_size = sizeof (diag210_t); memcpy (info->characteristics, &((dasd_diag_private_t *) device->private)->rdc_data, sizeof (diag210_t)); info->confdata_size = 0; return rc;}/* * max_blocks: We want to fit one CP into one page of memory so that we can * effectively use available resources. * The ccw_req_t has less than 256 bytes (including safety) * and diag_bio_t for each block has 16 bytes. * That makes: * (4096 - 256) / 16 = 240 blocks at maximum. */dasd_discipline_t dasd_diag_discipline = { owner: THIS_MODULE, name:"DIAG", ebcname:"DIAG", max_blocks:240, check_characteristics:dasd_diag_check_characteristics, fill_geometry:dasd_diag_fill_geometry, start_IO:dasd_start_diag, examine_error:dasd_diag_examine_error, build_cp_from_req:dasd_diag_build_cp_from_req, int_handler:(void *) dasd_ext_handler, fill_info:dasd_diag_fill_info, list:LIST_HEAD_INIT(dasd_diag_discipline.list),};intdasd_diag_init (void){ int rc = 0; if (MACHINE_IS_VM) { MESSAGE (KERN_INFO, "%s discipline initializing", dasd_diag_discipline.name); ASCEBC (dasd_diag_discipline.ebcname, 4); ctl_set_bit (0, 9); register_external_interrupt (0x2603, dasd_ext_handler); dasd_discipline_add (&dasd_diag_discipline); } else { MESSAGE (KERN_INFO, "Machine is not VM: %s discipline not initializing", dasd_diag_discipline.name); rc = -EINVAL; } return rc;}voiddasd_diag_cleanup (void){ if (MACHINE_IS_VM) { MESSAGE (KERN_INFO, "%s discipline cleaning up", dasd_diag_discipline.name); dasd_discipline_del (&dasd_diag_discipline); unregister_external_interrupt (0x2603, dasd_ext_handler); ctl_clear_bit (0, 9); } else { MESSAGE (KERN_INFO, "Machine is not VM: %s discipline not initializing", dasd_diag_discipline.name); }}#ifdef MODULEintinit_module (void){ int rc = 0; rc = dasd_diag_init (); return rc;}voidcleanup_module (void){ dasd_diag_cleanup (); return;}#endif/* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only. This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-indent-level: 4 * c-brace-imaginary-offset: 0 * c-brace-offset: -4 * c-argdecl-indent: 4 * c-label-offset: -4 * c-continued-statement-offset: 4 * c-continued-brace-offset: 0 * indent-tabs-mode: nil * tab-width: 8 * End: */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?