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

📄 dasd_eckd.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 3 页
字号:
	case WRITE:		if (recid < 3)			return DASD_ECKD_CCW_WRITE_KD_MT;		if (recid < blk_per_trk)			return DASD_ECKD_CCW_WRITE_MT;		if (recid < 2 * blk_per_trk)			return DASD_ECKD_CCW_WRITE_KD_MT;		return DASD_ECKD_CCW_WRITE_MT;		break;	default:		BUG ();	}	return 0;		// never executed}static ccw_req_t *dasd_eckd_build_cp_from_req (dasd_device_t * device, struct request *req){	ccw_req_t *rw_cp = NULL;	int rw_cmd;	int bhct;	long size;	ccw1_t *ccw;	DE_eckd_data_t *DE_data;	LO_eckd_data_t *LO_data;	struct buffer_head *bh;	dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;	int byt_per_blk = device->sizes.bp_block;	int shift = device->sizes.s2b_shift;	int blk_per_trk = recs_per_track (&(private->rdc_data), 0, byt_per_blk);	int btrk = (req->sector >> shift) / blk_per_trk;	int etrk = ((req->sector + req->nr_sectors - 1) >> shift) / blk_per_trk;	int recid = req->sector >> shift;	int locate4k_set = 0;	int nlocs = 0;	if (req->cmd == READ) {		rw_cmd = DASD_ECKD_CCW_READ_MT;	} else if (req->cmd == WRITE) {		rw_cmd = DASD_ECKD_CCW_WRITE_MT;	} else {		PRINT_ERR ("Unknown command %d\n", req->cmd);		return NULL;	}	/* Build the request */	/* count bhs to prevent errors, when bh smaller than block */	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);	}	if (btrk < 2 && private->uses_cdl) {		if (etrk < 2)                        nlocs = bhct;                else                        nlocs = 2 * blk_per_trk - recid;	}	rw_cp = dasd_alloc_request (dasd_eckd_discipline.name,                                     2 + nlocs + bhct + 1,                                    sizeof (DE_eckd_data_t) + (1 +                                                               nlocs) *                                    sizeof (LO_eckd_data_t),                                    device);	if (!rw_cp) {		return NULL;	}	DE_data = rw_cp->data;	LO_data = rw_cp->data + sizeof (DE_eckd_data_t);	ccw = rw_cp->cpaddr;	if (define_extent (ccw, DE_data, btrk, etrk, rw_cmd, device, rw_cp)) {                goto clear_rw_cp;        }	ccw->flags |= CCW_FLAG_CC;	for (bh = req->bh; bh != NULL;) {                for (size = 0; size < bh->b_size; size += byt_per_blk) {                        if (!locate4k_set) {                                // we need to chain a locate record before our rw-ccw                                ccw++;                                if ((recid / blk_per_trk) < 2                                    && private->uses_cdl) {                                        /* Do a locate record for our special blocks */                                        int cmd = dasd_eckd_cdl_cmd (device,recid, req->cmd);                                        if (locate_record (ccw,                                                        LO_data++,                                                       recid / blk_per_trk,                                                        recid % blk_per_trk + 1,                                                        1, cmd, device,                                                           dasd_eckd_cdl_reclen(device, recid), rw_cp)) {                                                goto clear_rw_cp;                                        }                                } else {                                        // Do a locate record for standard blocks */                                        if (locate_record (ccw,                                                        LO_data++,                                                       recid /blk_per_trk,                                                       recid %blk_per_trk + 1,                                                       (((req->sector +                                                          req->nr_sectors) >>                                                         shift) - recid),                                                        rw_cmd, device,                                                           device->sizes.bp_block, rw_cp)) {                                                goto clear_rw_cp;                                        }                                        locate4k_set = 1;                                }                                ccw->flags |= CCW_FLAG_CC;                        }                        ccw++;                        ccw->flags |= CCW_FLAG_CC;                        ccw->cmd_code = locate4k_set ? rw_cmd :                                dasd_eckd_cdl_cmd (device, recid, req->cmd);                        ccw->count = byt_per_blk;                        if (!locate4k_set) {                                ccw->count = dasd_eckd_cdl_reclen (device,recid);                                if (ccw->count < byt_per_blk) {                                    memset (bh->b_data + size + ccw->count,                                            0xE5, byt_per_blk - ccw->count);                                }                        }                        if (dasd_set_normalized_cda (ccw, __pa (bh->b_data+size), rw_cp, device)) {                                goto clear_rw_cp;                        }                        recid++;                }                bh = bh->b_reqnext;	}	ccw->flags &= ~(CCW_FLAG_DC | CCW_FLAG_CC);	rw_cp->device = device;	rw_cp->expires = 5 * TOD_MIN;	/* 5 minutes */	rw_cp->req = req;	rw_cp->lpm = LPM_ANYPATH;	rw_cp->retries = 2;	asm volatile ("STCK %0":"=m" (rw_cp->buildclk));	check_then_set (&rw_cp->status, CQR_STATUS_EMPTY, CQR_STATUS_FILLED);        goto out; clear_rw_cp:        dasd_free_request (rw_cp, device);        rw_cp=NULL; out:	return rw_cp;}#if 0intdasd_eckd_cleanup_request (ccw_req_t * cqr){	int ret = 0;	struct request *req = cqr->req;	dasd_device_t *device = cqr->device;	int byt_per_blk = device->sizes.bp_block;	for (bh = req->bh; bh != NULL;) {		if (bh->b_size > byt_per_blk) {			for (size = 0; size < bh->b_size; size += byt_per_blk) {				ccw++;				ccw->flags |= CCW_FLAG_CC;				ccw->cmd_code = rw_cmd;				ccw->count = byt_per_blk;				set_normalized_cda (ccw,						    __pa (bh->b_data + size));			}			bh = bh->b_reqnext;		} else {	/* group N bhs to fit into byt_per_blk */			for (size = 0; bh != NULL && size < byt_per_blk;) {				ccw++;				ccw->flags |= CCW_FLAG_DC;				ccw->cmd_code = rw_cmd;				ccw->count = bh->b_size;				set_normalized_cda (ccw, __pa (bh->b_data));				size += bh->b_size;				bh = bh->b_reqnext;			}		}	}	return ret;}#endif/* * DASD_ECKD_RESERVE * * DESCRIPTION *    Buils a channel programm to reserve a device. *    Options are set to 'synchronous wait for interrupt' and *    'timeout the request'. This leads to an terminate IO if  *    the interrupt is outstanding for a certain time.  */ccw_req_t *dasd_eckd_reserve (struct dasd_device_t * device){	ccw_req_t *cqr =	    dasd_alloc_request (dasd_eckd_discipline.name, 1 + 1, 0, device);	if (cqr == NULL) {		printk (KERN_WARNING PRINTK_HEADER			"No memory to allocate initialization request\n");		return NULL;	}	cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RESERVE;	cqr->device  = device;	cqr->retries = 0;	cqr->expires = 10 * TOD_SEC;        cqr->options = (DOIO_WAIT_FOR_INTERRUPT | DOIO_TIMEOUT); /* timeout reqest */	cqr->status  = CQR_STATUS_FILLED;	return cqr; }/* * DASD_ECKD_RELEASE * * DESCRIPTION *    Buils a channel programm to releases a prior reserved  *    (see dasd_eckd_reserve) device. */ccw_req_t *dasd_eckd_release (struct dasd_device_t * device){	ccw_req_t *cqr =	    dasd_alloc_request (dasd_eckd_discipline.name, 1 + 1, 0, device);	if (cqr == NULL) {		printk (KERN_WARNING PRINTK_HEADER			"No memory to allocate initialization request\n");		return NULL;	}	cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RELEASE;	cqr->device  = device;	cqr->retries = 0;	cqr->expires = 10 * TOD_SEC;        cqr->options = (DOIO_WAIT_FOR_INTERRUPT | DOIO_TIMEOUT); /* timeout reqest */	cqr->status  = CQR_STATUS_FILLED;	return cqr;}/* * DASD_ECKD_STEAL_LOCK * * DESCRIPTION *    Buils a channel programm to break a device's reservation.  *    (unconditional reserve) */ccw_req_t *dasd_eckd_steal_lock (struct dasd_device_t * device){	ccw_req_t *cqr =	    dasd_alloc_request (dasd_eckd_discipline.name, 1 + 1, 0, device);	if (cqr == NULL) {		printk (KERN_WARNING PRINTK_HEADER			"No memory to allocate initialization request\n");		return NULL;	}	cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SLCK;	cqr->device  = device;	cqr->retries = 0;	cqr->expires = 10 * TOD_SEC;        cqr->options = (DOIO_WAIT_FOR_INTERRUPT | DOIO_TIMEOUT); /* timeout reqest */	cqr->status  = CQR_STATUS_FILLED;	return cqr;}static inline ccw1_t *dasd_eckd_find_cmd (ccw_req_t * cqr, int cmd){	ccw1_t *cp;	cp = cqr->cpaddr;	do {		if (cp->cmd_code == cmd)			return cp;		if (cp->cmd_code == CCW_CMD_TIC) {			cp = (ccw1_t *) (long) cp->cda;			continue;		}		if (cp->flags & (CCW_FLAG_DC | CCW_FLAG_CC)) {			cp++;			continue;		}		break;	} while (1);	return NULL;}static ccw_req_t *dasd_eckd_merge_cp (dasd_device_t * device){	return NULL;}static intdasd_eckd_fill_info (dasd_device_t * device, dasd_information_t * info){	int rc = 0;	info->label_block = 2;	if (((dasd_eckd_private_t *) device->private)->uses_cdl)		info->FBA_layout = 0;	else		info->FBA_layout = 1;	info->characteristics_size = sizeof (dasd_eckd_characteristics_t);	memcpy (info->characteristics,		&((dasd_eckd_private_t *) device->private)->rdc_data,		sizeof (dasd_eckd_characteristics_t));	info->confdata_size = sizeof (dasd_eckd_confdata_t);	memcpy (info->configuration_data,		&((dasd_eckd_private_t *) device->private)->conf_data,		sizeof (dasd_eckd_confdata_t));	return rc;}static char*dasd_eckd_dump_sense (struct dasd_device_t *device,                       ccw_req_t            *req){	char *page = (char *) get_free_page (GFP_ATOMIC);	devstat_t *stat = &device->dev_status;	char *sense = stat->ii.sense.data;	int len, sl, sct;	if (page == NULL) {                printk (KERN_ERR PRINTK_HEADER                        "No memory to dump sense data\n");		return NULL;	}	len = sprintf (page, KERN_ERR PRINTK_HEADER		       "device %04X on irq %d: I/O status report:\n",		       device->devinfo.devno, device->devinfo.irq);	len += sprintf (page + len, KERN_ERR PRINTK_HEADER			"in req: %p CS: 0x%02X DS: 0x%02X\n",			req, stat->cstat, stat->dstat);	len += sprintf (page + len, KERN_ERR PRINTK_HEADER			"Failing CCW: %p\n", (void *) (long) stat->cpa);	{		ccw1_t *act = req->cpaddr;		int i = req->cplength;		do {#ifdef ERP_DEBUG			printk (KERN_ERR "CCW %p: %08X %08X\n",				act, ((int *) act)[0], ((int *) act)[1]);			printk (KERN_ERR "DAT: %08X %08X %08X %08X\n",				((int *) act->cda)[0], ((int *) act->cda)[1],				((int *) act->cda)[2], ((int *) act->cda)[3]);#endif				/* ERP_DEBUG */			act++;		} while (--i);	}	if (stat->flag & DEVSTAT_FLAG_SENSE_AVAIL) {		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",						sense[8 * sl + sct]);			}			len += sprintf (page + len, "\n");		}		if (sense[27] & DASD_SENSE_BIT_0) {			/* 24 Byte Sense Data */			len += sprintf (page + len, KERN_ERR PRINTK_HEADER					"24 Byte: %x MSG %x, %s MSGb to SYSOP\n",					sense[7] >> 4, sense[7] & 0x0f,					sense[1] & 0x10 ? "" : "no");		} else {			/* 32 Byte Sense Data */			len += sprintf (page + len, KERN_ERR PRINTK_HEADER					"32 Byte: Format: %x Exception class %x\n",					sense[6] & 0x0f, sense[22] >> 4);		}	}        printk ("Sense data:\n%s",                 page);        free_page ((unsigned long) page);        	return NULL;}dasd_discipline_t dasd_eckd_discipline = {        owner: THIS_MODULE,	name:"ECKD",	ebcname:"ECKD",	max_blocks:255,	id_check:dasd_eckd_id_check,	check_characteristics:dasd_eckd_check_characteristics,	init_analysis:dasd_eckd_init_analysis,	do_analysis:dasd_eckd_do_analysis,	fill_geometry:dasd_eckd_fill_geometry,	start_IO:dasd_start_IO,	term_IO:dasd_term_IO,	format_device:dasd_eckd_format_device,	examine_error:dasd_eckd_examine_error,	erp_action:dasd_eckd_erp_action,	erp_postaction:dasd_eckd_erp_postaction,	build_cp_from_req:dasd_eckd_build_cp_from_req,	dump_sense:dasd_eckd_dump_sense,	int_handler:dasd_int_handler,	reserve:dasd_eckd_reserve,	release:dasd_eckd_release,        steal_lock:dasd_eckd_steal_lock,	merge_cp:dasd_eckd_merge_cp,	fill_info:dasd_eckd_fill_info,};intdasd_eckd_init (void){	int rc = 0;	printk (KERN_INFO PRINTK_HEADER		"%s discipline initializing\n", dasd_eckd_discipline.name);	ASCEBC (dasd_eckd_discipline.ebcname, 4);	dasd_discipline_add (&dasd_eckd_discipline);#ifdef CONFIG_DASD_DYNAMIC	{		int i;		for (i = 0;		     i < sizeof (dasd_eckd_known_devices) / sizeof (devreg_t);		     i++) {			printk (KERN_INFO PRINTK_HEADER				"We are interested in: CU %04X/%02x\n",				dasd_eckd_known_devices[i].ci.hc.ctype,				dasd_eckd_known_devices[i].ci.hc.cmode);			s390_device_register (&dasd_eckd_known_devices[i]);		}	}#endif				/* CONFIG_DASD_DYNAMIC */	return rc;}voiddasd_eckd_cleanup (void){	printk (KERN_INFO PRINTK_HEADER		"%s discipline cleaning up\n", dasd_eckd_discipline.name);#ifdef CONFIG_DASD_DYNAMIC	{		int i;		for (i = 0;		     i < sizeof (dasd_eckd_known_devices) / sizeof (devreg_t);		     i++) {			printk (KERN_INFO PRINTK_HEADER				"We were interested in: CU %04X/%02x\n",				dasd_eckd_known_devices[i].ci.hc.ctype,				dasd_eckd_known_devices[i].ci.hc.cmode);			s390_device_unregister (&dasd_eckd_known_devices[i]);		}	}#endif				/* CONFIG_DASD_DYNAMIC */	dasd_discipline_del (&dasd_eckd_discipline);}#ifdef MODULEintinit_module (void){	int rc = 0;	rc = dasd_eckd_init ();	return rc;}voidcleanup_module (void){	dasd_eckd_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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -