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 + -
显示快捷键?