⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dasd_diag.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
}/* Check whether device can be controlled by DIAG discipline. Return zero on * success, non-zero otherwise. */static intdasd_diag_check_device(struct dasd_device *device){	struct dasd_diag_private *private;	struct dasd_diag_characteristics *rdc_data;	struct dasd_diag_bio bio;	struct dasd_diag_cms_label *label;	blocknum_t end_block;	unsigned int sb, bsize;	int rc;	private = (struct dasd_diag_private *) device->private;	if (private == NULL) {		private = kmalloc(sizeof(struct dasd_diag_private),GFP_KERNEL);		if (private == NULL) {			DEV_MESSAGE(KERN_WARNING, device, "%s",				"memory allocation failed for private data");			return -ENOMEM;		}		device->private = (void *) private;	}	/* Read Device Characteristics */	rdc_data = (void *) &(private->rdc_data);	rdc_data->dev_nr = _ccw_device_get_device_number(device->cdev);	rdc_data->rdc_len = sizeof (struct dasd_diag_characteristics);	rc = diag210((struct diag210 *) rdc_data);	if (rc) {		DEV_MESSAGE(KERN_WARNING, device, "failed to retrieve device "			    "information (rc=%d)", rc);		return -ENOTSUPP;	}	/* Figure out position of label block */	switch (private->rdc_data.vdev_class) {	case DEV_CLASS_FBA:		private->pt_block = 1;		break;	case DEV_CLASS_ECKD:		private->pt_block = 2;		break;	default:		DEV_MESSAGE(KERN_WARNING, device, "unsupported device class "			    "(class=%d)", private->rdc_data.vdev_class);		return -ENOTSUPP;	}	DBF_DEV_EVENT(DBF_INFO, device,		      "%04X: %04X on real %04X/%02X",		      rdc_data->dev_nr,		      rdc_data->vdev_type,		      rdc_data->rdev_type, rdc_data->rdev_model);	/* terminate all outstanding operations */	mdsk_term_io(device);	/* figure out blocksize of device */	label = (struct dasd_diag_cms_label *) get_zeroed_page(GFP_KERNEL);	if (label == NULL)  {		DEV_MESSAGE(KERN_WARNING, device, "%s",			    "No memory to allocate initialization request");		return -ENOMEM;	}	rc = 0;	end_block = 0;	/* try all sizes - needed for ECKD devices */	for (bsize = 512; bsize <= PAGE_SIZE; bsize <<= 1) {		mdsk_init_io(device, bsize, 0, &end_block);		memset(&bio, 0, sizeof (struct dasd_diag_bio));		bio.type = MDSK_READ_REQ;		bio.block_number = private->pt_block + 1;		bio.buffer = label;		memset(&private->iob, 0, sizeof (struct dasd_diag_rw_io));		private->iob.dev_nr = rdc_data->dev_nr;		private->iob.key = 0;		private->iob.flags = 0;	/* do synchronous io */		private->iob.block_count = 1;		private->iob.interrupt_params = 0;		private->iob.bio_list = &bio;		private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;		rc = dia250(&private->iob, RW_BIO);		if (rc == 3) {			DEV_MESSAGE(KERN_WARNING, device, "%s",				"DIAG call failed");			rc = -EOPNOTSUPP;			goto out;		}		mdsk_term_io(device);		if (rc == 0)			break;	}	if (bsize > PAGE_SIZE) {		DEV_MESSAGE(KERN_WARNING, device, "device access failed "			    "(rc=%d)", rc);		rc = -EIO;		goto out;	}	/* check for label block */	if (memcmp(label->label_id, DASD_DIAG_CMS1,		  sizeof(DASD_DIAG_CMS1)) == 0) {		/* get formatted blocksize from label block */		bsize = (unsigned int) label->block_size;		device->blocks = (unsigned long) label->block_count;	} else		device->blocks = end_block;	device->bp_block = bsize;	device->s2b_shift = 0;	/* bits to shift 512 to get a block */	for (sb = 512; sb < bsize; sb = sb << 1)		device->s2b_shift++;	rc = mdsk_init_io(device, device->bp_block, 0, NULL);	if (rc) {		DEV_MESSAGE(KERN_WARNING, device, "DIAG initialization "			"failed (rc=%d)", rc);		rc = -EIO;	} else {		DEV_MESSAGE(KERN_INFO, device,			    "(%ld B/blk): %ldkB",			    (unsigned long) device->bp_block,			    (unsigned long) (device->blocks <<				device->s2b_shift) >> 1);	}out:	free_page((long) label);	return rc;}/* Fill in virtual disk geometry for device. Return zero on success, non-zero * otherwise. */static intdasd_diag_fill_geometry(struct dasd_device *device, struct hd_geometry *geo){	if (dasd_check_blocksize(device->bp_block) != 0)		return -EINVAL;	geo->cylinders = (device->blocks << device->s2b_shift) >> 10;	geo->heads = 16;	geo->sectors = 128 >> device->s2b_shift;	return 0;}static dasd_era_tdasd_diag_examine_error(struct dasd_ccw_req * cqr, struct irb * stat){	return dasd_era_fatal;}static dasd_erp_fn_tdasd_diag_erp_action(struct dasd_ccw_req * cqr){	return dasd_default_erp_action;}static dasd_erp_fn_tdasd_diag_erp_postaction(struct dasd_ccw_req * cqr){	return dasd_default_erp_postaction;}/* Create DASD request from block device request. Return pointer to new * request on success, ERR_PTR otherwise. */static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device * device, struct request *req){	struct dasd_ccw_req *cqr;	struct dasd_diag_req *dreq;	struct dasd_diag_bio *dbio;	struct bio *bio;	struct bio_vec *bv;	char *dst;	unsigned int count, datasize;	sector_t recid, first_rec, last_rec;	unsigned int blksize, off;	unsigned char rw_cmd;	int i;	if (rq_data_dir(req) == READ)		rw_cmd = MDSK_READ_REQ;	else if (rq_data_dir(req) == WRITE)		rw_cmd = MDSK_WRITE_REQ;	else		return ERR_PTR(-EINVAL);	blksize = device->bp_block;	/* Calculate record id of first and last block. */	first_rec = req->sector >> device->s2b_shift;	last_rec = (req->sector + req->nr_sectors - 1) >> device->s2b_shift;	/* Check struct bio and count the number of blocks for the request. */	count = 0;	rq_for_each_bio(bio, req) {		bio_for_each_segment(bv, bio, i) {			if (bv->bv_len & (blksize - 1))				/* Fba can only do full blocks. */				return ERR_PTR(-EINVAL);			count += bv->bv_len >> (device->s2b_shift + 9);		}	}	/* Paranoia. */	if (count != last_rec - first_rec + 1)		return ERR_PTR(-EINVAL);	/* Build the request */	datasize = sizeof(struct dasd_diag_req) +		count*sizeof(struct dasd_diag_bio);	cqr = dasd_smalloc_request(dasd_diag_discipline.name, 0,				   datasize, device);	if (IS_ERR(cqr))		return cqr;		dreq = (struct dasd_diag_req *) cqr->data;	dreq->block_count = count;	dbio = dreq->bio;	recid = first_rec;	rq_for_each_bio(bio, req) {		bio_for_each_segment(bv, bio, i) {			dst = page_address(bv->bv_page) + bv->bv_offset;			for (off = 0; off < bv->bv_len; off += blksize) {				memset(dbio, 0, sizeof (struct dasd_diag_bio));				dbio->type = rw_cmd;				dbio->block_number = recid + 1;				dbio->buffer = dst;				dbio++;				dst += blksize;				recid++;			}		}	}	cqr->retries = DIAG_MAX_RETRIES;	cqr->buildclk = get_clock();	cqr->device = device;	cqr->expires = DIAG_TIMEOUT;	cqr->status = DASD_CQR_FILLED;	return cqr;}/* Release DASD request. Return non-zero if request was successful, zero * otherwise. */static intdasd_diag_free_cp(struct dasd_ccw_req *cqr, struct request *req){	int status;	status = cqr->status == DASD_CQR_DONE;	dasd_sfree_request(cqr, cqr->device);	return status;}/* Fill in IOCTL data for device. */static intdasd_diag_fill_info(struct dasd_device * device,		    struct dasd_information2_t * info){	struct dasd_diag_private *private;	private = (struct dasd_diag_private *) device->private;	info->label_block = (unsigned int) private->pt_block;	info->FBA_layout = 1;	info->format = DASD_FORMAT_LDL;	info->characteristics_size = sizeof (struct dasd_diag_characteristics);	memcpy(info->characteristics,	       &((struct dasd_diag_private *) device->private)->rdc_data,	       sizeof (struct dasd_diag_characteristics));	info->confdata_size = 0;	return 0;}static voiddasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,		     struct irb *stat){	DEV_MESSAGE(KERN_ERR, device, "%s",		    "dump sense not available for DIAG data");}struct dasd_discipline dasd_diag_discipline = {	.owner = THIS_MODULE,	.name = "DIAG",	.ebcname = "DIAG",	.max_blocks = DIAG_MAX_BLOCKS,	.check_device = dasd_diag_check_device,	.fill_geometry = dasd_diag_fill_geometry,	.start_IO = dasd_start_diag,	.term_IO = dasd_diag_term_IO,	.examine_error = dasd_diag_examine_error,	.erp_action = dasd_diag_erp_action,	.erp_postaction = dasd_diag_erp_postaction,	.build_cp = dasd_diag_build_cp,	.free_cp = dasd_diag_free_cp,	.dump_sense = dasd_diag_dump_sense,	.fill_info = dasd_diag_fill_info,};static int __initdasd_diag_init(void){	if (!MACHINE_IS_VM) {		MESSAGE_LOG(KERN_INFO,			    "Machine is not VM: %s "			    "discipline not initializing",			    dasd_diag_discipline.name);		return -ENODEV;	}	ASCEBC(dasd_diag_discipline.ebcname, 4);	ctl_set_bit(0, 9);	register_external_interrupt(0x2603, dasd_ext_handler);	dasd_diag_discipline_pointer = &dasd_diag_discipline;	return 0;}static void __exitdasd_diag_cleanup(void){	unregister_external_interrupt(0x2603, dasd_ext_handler);	ctl_clear_bit(0, 9);	dasd_diag_discipline_pointer = NULL;}module_init(dasd_diag_init);module_exit(dasd_diag_cleanup);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -