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

📄 dasd_fba.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* Build locate_record + read/write ccws. */	idaws = (unsigned long *) (cqr->data + sizeof(struct DE_fba_data));	LO_data = (struct LO_fba_data *) (idaws + cidaw);	/* Locate record for all blocks for smart devices. */	if (private->rdc_data.mode.bits.data_chain != 0) {		ccw[-1].flags |= CCW_FLAG_CC;		locate_record(ccw++, LO_data++, rq_data_dir(req), 0, count);	}	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;		if (dasd_page_cache) {			char *copy = kmem_cache_alloc(dasd_page_cache,						      SLAB_DMA | __GFP_NOWARN);			if (copy && rq_data_dir(req) == WRITE)				memcpy(copy + bv->bv_offset, dst, bv->bv_len);			if (copy)				dst = copy + bv->bv_offset;		}		for (off = 0; off < bv->bv_len; off += blksize) {			/* Locate record for stupid devices. */			if (private->rdc_data.mode.bits.data_chain == 0) {				ccw[-1].flags |= CCW_FLAG_CC;				locate_record(ccw, LO_data++,					      rq_data_dir(req),					      recid - first_rec, 1);				ccw->flags = CCW_FLAG_CC;				ccw++;			} else {				if (recid > first_rec)					ccw[-1].flags |= CCW_FLAG_DC;				else					ccw[-1].flags |= CCW_FLAG_CC;			}			ccw->cmd_code = cmd;			ccw->count = device->bp_block;			if (idal_is_needed(dst, blksize)) {				ccw->cda = (__u32)(addr_t) idaws;				ccw->flags = CCW_FLAG_IDA;				idaws = idal_create_words(idaws, dst, blksize);			} else {				ccw->cda = (__u32)(addr_t) dst;				ccw->flags = 0;			}			ccw++;			dst += blksize;			recid++;		}	}	cqr->device = device;	cqr->expires = 5 * 60 * HZ;	/* 5 minutes */	cqr->retries = 32;	cqr->buildclk = get_clock();	cqr->status = DASD_CQR_FILLED;	return cqr;}static intdasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req){	struct dasd_fba_private *private;	struct ccw1 *ccw;	struct bio *bio;	struct bio_vec *bv;	char *dst, *cda;	unsigned int blksize, off;	int i, status;	if (!dasd_page_cache)		goto out;	private = (struct dasd_fba_private *) cqr->device->private;	blksize = cqr->device->bp_block;	ccw = cqr->cpaddr;	/* Skip over define extent & locate record. */	ccw++;	if (private->rdc_data.mode.bits.data_chain != 0)		ccw++;	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) {			/* Skip locate record. */			if (private->rdc_data.mode.bits.data_chain == 0)				ccw++;			if (dst) {				if (ccw->flags & CCW_FLAG_IDA)					cda = *((char **)((addr_t) ccw->cda));				else					cda = (char *)((addr_t) ccw->cda);				if (dst != cda) {					if (rq_data_dir(req) == READ)						memcpy(dst, cda, bv->bv_len);					kmem_cache_free(dasd_page_cache,					    (void *)((addr_t)cda & PAGE_MASK));				}				dst = NULL;			}			ccw++;		}	}out:	status = cqr->status == DASD_CQR_DONE;	dasd_sfree_request(cqr, cqr->device);	return status;}static intdasd_fba_fill_info(struct dasd_device * device,		   struct dasd_information2_t * info){	info->label_block = 1;	info->FBA_layout = 1;	info->format = DASD_FORMAT_LDL;	info->characteristics_size = sizeof(struct dasd_fba_characteristics);	memcpy(info->characteristics,	       &((struct dasd_fba_private *) device->private)->rdc_data,	       sizeof (struct dasd_fba_characteristics));	info->confdata_size = 0;	return 0;}static voiddasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,		    struct irb *irb){	char *page;	struct ccw1 *act, *end, *last;	int len, sl, sct, count;	page = (char *) get_zeroed_page(GFP_ATOMIC);	if (page == NULL) {		DEV_MESSAGE(KERN_ERR, device, " %s",			    "No memory to dump sense data");		return;	}	len = sprintf(page, KERN_ERR PRINTK_HEADER		      " I/O status report for device %s:\n",		      device->cdev->dev.bus_id);	len += sprintf(page + len, KERN_ERR PRINTK_HEADER		       " in req: %p CS: 0x%02X DS: 0x%02X\n", req,		       irb->scsw.cstat, irb->scsw.dstat);	len += sprintf(page + len, KERN_ERR PRINTK_HEADER		       " device %s: Failing CCW: %p\n",		       device->cdev->dev.bus_id,		       (void *) (addr_t) irb->scsw.cpa);	if (irb->esw.esw0.erw.cons) {		for (sl = 0; sl < 4; sl++) {			len += sprintf(page + len, KERN_ERR PRINTK_HEADER				       " Sense(hex) %2d-%2d:",				       (8 * sl), ((8 * sl) + 7));			for (sct = 0; sct < 8; sct++) {				len += sprintf(page + len, " %02x",					       irb->ecw[8 * sl + sct]);			}			len += sprintf(page + len, "\n");		}	} else {	        len += sprintf(page + len, KERN_ERR PRINTK_HEADER			       " SORRY - NO VALID SENSE AVAILABLE\n");	}	MESSAGE_LOG(KERN_ERR, "%s",		    page + sizeof(KERN_ERR PRINTK_HEADER));	/* dump the Channel Program */	/* print first CCWs (maximum 8) */	act = req->cpaddr;        for (last = act; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++);	end = min(act + 8, last);	len = sprintf(page, KERN_ERR PRINTK_HEADER		      " Related CP in req: %p\n", req);	while (act <= end) {		len += sprintf(page + len, KERN_ERR PRINTK_HEADER			       " CCW %p: %08X %08X DAT:",			       act, ((int *) act)[0], ((int *) act)[1]);		for (count = 0; count < 32 && count < act->count;		     count += sizeof(int))			len += sprintf(page + len, " %08X",				       ((int *) (addr_t) act->cda)				       [(count>>2)]);		len += sprintf(page + len, "\n");		act++;	}	MESSAGE_LOG(KERN_ERR, "%s",		    page + sizeof(KERN_ERR PRINTK_HEADER));	/* print failing CCW area */	len = 0;	if (act <  ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2) {		act = ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2;		len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n");	}	end = min((struct ccw1 *)(addr_t) irb->scsw.cpa + 2, last);	while (act <= end) {		len += sprintf(page + len, KERN_ERR PRINTK_HEADER			       " CCW %p: %08X %08X DAT:",			       act, ((int *) act)[0], ((int *) act)[1]);		for (count = 0; count < 32 && count < act->count;		     count += sizeof(int))			len += sprintf(page + len, " %08X",				       ((int *) (addr_t) act->cda)				       [(count>>2)]);		len += sprintf(page + len, "\n");		act++;	}	/* print last CCWs */	if (act <  last - 2) {		act = last - 2;		len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n");	}	while (act <= last) {		len += sprintf(page + len, KERN_ERR PRINTK_HEADER			       " CCW %p: %08X %08X DAT:",			       act, ((int *) act)[0], ((int *) act)[1]);		for (count = 0; count < 32 && count < act->count;		     count += sizeof(int))			len += sprintf(page + len, " %08X",				       ((int *) (addr_t) act->cda)				       [(count>>2)]);		len += sprintf(page + len, "\n");		act++;	}	if (len > 0)		MESSAGE_LOG(KERN_ERR, "%s",			    page + sizeof(KERN_ERR PRINTK_HEADER));	free_page((unsigned long) page);}/* * max_blocks is dependent on the amount of storage that is available * in the static io buffer for each device. Currently each device has * 8192 bytes (=2 pages). For 64 bit one dasd_mchunkt_t structure has * 24 bytes, the struct dasd_ccw_req has 136 bytes and each block can use * up to 16 bytes (8 for the ccw and 8 for the idal pointer). In * addition we have one define extent ccw + 16 bytes of data and a  * locate record ccw for each block (stupid devices!) + 16 bytes of data. * That makes: * (8192 - 24 - 136 - 8 - 16) / 40 = 200.2 blocks at maximum. * We want to fit two into the available memory so that we can immediately * start the next request if one finishes off. That makes 100.1 blocks * for one request. Give a little safety and the result is 96. */static struct dasd_discipline dasd_fba_discipline = {	.owner = THIS_MODULE,	.name = "FBA ",	.ebcname = "FBA ",	.max_blocks = 96,	.check_device = dasd_fba_check_characteristics,	.do_analysis = dasd_fba_do_analysis,	.fill_geometry = dasd_fba_fill_geometry,	.start_IO = dasd_start_IO,	.term_IO = dasd_term_IO,	.examine_error = dasd_fba_examine_error,	.erp_action = dasd_fba_erp_action,	.erp_postaction = dasd_fba_erp_postaction,	.build_cp = dasd_fba_build_cp,	.free_cp = dasd_fba_free_cp,	.dump_sense = dasd_fba_dump_sense,	.fill_info = dasd_fba_fill_info,};static int __initdasd_fba_init(void){	int ret;	ASCEBC(dasd_fba_discipline.ebcname, 4);	ret = ccw_driver_register(&dasd_fba_driver);	if (ret)		return ret;	dasd_generic_auto_online(&dasd_fba_driver);	return 0;}static void __exitdasd_fba_cleanup(void){	ccw_driver_unregister(&dasd_fba_driver);}module_init(dasd_fba_init);module_exit(dasd_fba_cleanup);/* * 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: 1 * tab-width: 8 * End: */

⌨️ 快捷键说明

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