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

📄 dasd.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
          type = dasd_none;        }        	FUNCTION_EXIT ("check_type");	return type;}static intdasd_read_characteristics (dasd_information_t * info){	int rc;	int ct = 0;	dev_info_t *di;	dasd_type_t dt;	FUNCTION_ENTRY ("read_characteristics");	if (info == NULL) {		return -ENODEV;	}	di = &(info->info);	if (di == NULL) {		return -ENODEV;	}	dt = check_type (di);	/* Some cross-checks, if the cu supports RDC */	if (MATCH (di, == 0x2835, ||1, ||1, ||1) ||	    MATCH (di, == 0x3830, ||1, ||1, ||1) ||	    MATCH (di, == 0x3830, ||1, ||1, ||1) ||	    MATCH (di, == 0x3990, <=0x03, == 0x3380, <=0x0d)) {		PRINT_WARN ("Device %d (%x/%x at %x/%x) supports no RDC\n",			    info->info.irq,			    di->sid_data.dev_type,			    di->sid_data.dev_model,			    di->sid_data.cu_type,			    di->sid_data.cu_model);		return -EINVAL;	}	switch (dt) {#ifdef CONFIG_DASD_ECKD	case dasd_eckd:          ct = 64;          rc = read_dev_chars (info->info.irq,                               (void *) &(info->rdc_data), ct);		break;#endif				/*  CONFIG_DASD_ECKD */#ifdef CONFIG_DASD_MDSK	case dasd_mdsk:		ct = 0;		break;#endif				/*  CONFIG_DASD_MDSK */	default:		INTERNAL_ERROR ("don't know dasd type %d\n", dt);	}	if (rc) {		PRINT_WARN ("RDC resulted in rc=%d\n", rc);	}	FUNCTION_EXIT ("read_characteristics");	return rc;}/* How many sectors must be in a request to dequeue it ? */#define QUEUE_BLOCKS 25#define QUEUE_SECTORS (QUEUE_BLOCKS << dasd_info[di]->sizes.s2b_shift)/* How often to retry an I/O before raising an error */#define DASD_MAX_RETRIES 5static inline cqr_t *dasd_cqr_from_req (struct request *req){	cqr_t *cqr = NULL;	int di;	dasd_information_t *info;	if (!req) {		PRINT_ERR ("No request passed!");		return NULL;	}	di = DEVICE_NR (req->rq_dev);	info = dasd_info[di];	if (!info)		return NULL;	/* if applicable relocate block */        if (MINOR (req->rq_dev) & ((1 << PARTN_BITS) - 1) ) {          req->sector +=             dd_gendisk.part[MINOR(req->rq_dev)].start_sect;        }	/* Now check for consistency */	if (!req->nr_sectors) {		PRINT_WARN ("req: %p dev: %08x sector: %ld nr_sectors: %ld bh: %p\n",		     req, req->rq_dev, req->sector, req->nr_sectors, req->bh);		return NULL;	}	if (((req->sector + req->nr_sectors) >> 1) > info->sizes.kbytes) {		printk (KERN_ERR PRINTK_HEADER			"Requesting I/O past end of device %d\n",			di);		return NULL;	}	cqr = dasd_disciplines[info->type]->get_req_ccw (di, req);	if (!cqr) {		PRINT_WARN ("empty CQR generated\n");	} else {		cqr->req = req;		cqr->int4cqr = cqr;		cqr->devindex = di;#ifdef DASD_PROFILE		asm volatile ("STCK %0":"=m" (cqr->buildclk));#endif				/* DASD_PROFILE */		if (atomic_compare_and_swap (CQR_STATUS_EMPTY,					     CQR_STATUS_FILLED,					     &cqr->status)) {			PRINT_WARN ("cqr from req stat changed %d\n",				    atomic_read (&cqr->status));		}	}	return cqr;}intdasd_start_IO (cqr_t * cqr){	int rc = 0;	int retries = DASD_SSCH_RETRIES;	int di, irq;	dasd_debug ((unsigned long) cqr);	/* cqr */	if (!cqr) {		PRINT_WARN ("(start_IO) no cqr passed\n");		return -EINVAL;	}	if (cqr->magic != DASD_MAGIC) {		PRINT_WARN ("(start_IO) magic number mismatch\n");		return -EINVAL;	}	if (atomic_compare_and_swap (CQR_STATUS_QUEUED,				     CQR_STATUS_IN_IO,				     &cqr->status)) {		PRINT_WARN ("start_IO: status changed %d\n",			    atomic_read (&cqr->status));		atomic_set (&cqr->status, CQR_STATUS_ERROR);		return -EINVAL;	}        di = cqr->devindex;	irq = dasd_info[di]->info.irq;	do {		asm volatile ("STCK %0":"=m" (cqr->startclk));		rc = do_IO (irq, cqr->cpaddr, (long) cqr, 0x00, cqr->options);		switch (rc) {		case 0:			if (!(cqr->options & DOIO_WAIT_FOR_INTERRUPT))                        	atomic_set_mask (DASD_CHANQ_BUSY,                                	         &dasd_info[di]->queue.flags);			break;		case -ENODEV:			PRINT_WARN ("cqr %p: 0x%04x error, %d retries left\n",				    cqr, dasd_info[di]->info.devno, retries);			break;		case -EIO:			PRINT_WARN ("cqr %p: 0x%04x I/O, %d retries left\n",				    cqr, dasd_info[di]->info.devno, retries);			break;		case -EBUSY:	/* set up timer, try later */						PRINT_WARN ("cqr %p: 0x%04x busy, %d retries left\n",				    cqr, dasd_info[di]->info.devno, retries);			break;		default:						PRINT_WARN ("cqr %p: 0x%04x %d, %d retries left\n",				    cqr, rc, dasd_info[di]->info.devno,                                    retries);			break;		}	} while (rc && --retries);	if (rc) {		if (atomic_compare_and_swap (CQR_STATUS_IN_IO,					     CQR_STATUS_ERROR,					     &cqr->status)) {			PRINT_WARN ("start_IO:(done) status changed %d\n",				    atomic_read (&cqr->status));		        atomic_set (&cqr->status, CQR_STATUS_ERROR);		}        }	return rc;}static inlinevoiddasd_end_cqr (cqr_t * cqr, int uptodate){	struct request *req = cqr->req;	asm volatile ("STCK %0":"=m" (cqr->endclk));#ifdef DASD_PROFILE	dasd_profile_add (cqr);#endif				/* DASD_PROFILE */	dasd_chanq_deq (&dasd_info[cqr->devindex]->queue, cqr);        if (req) {                dasd_end_request (req, uptodate);        }}voiddasd_dump_sense (devstat_t * stat){	int sl, sct;	if ( ! stat->flag | DEVSTAT_FLAG_SENSE_AVAIL) {		PRINT_INFO("I/O status w/o sense data");        } else {		printk (KERN_INFO PRINTK_HEADER			"-------------------I/O result:-----------\n");		for (sl = 0; sl < 4; sl++) {			printk (KERN_INFO PRINTK_HEADER "Sense:");			for (sct = 0; sct < 8; sct++) {				printk (" %2d:0x%02X", 8 * sl + sct,					stat->ii.sense.data[8 * sl + sct]);			}			printk ("\n");		}		}}static int register_dasd_last (int di){	int rc = 0;	int minor;        struct buffer_head *bh;	rc = dasd_disciplines[dasd_info[di]->type]->fill_sizes_last (di);	switch (rc) {	case -EMEDIUMTYPE:		dasd_info[di]->flags |= DASD_INFO_FLAGS_NOT_FORMATTED;		break;	}	PRINT_INFO ("%ld kB <- 'soft'-block: %d, hardsect %d Bytes\n",		    dasd_info[di]->sizes.kbytes,		    dasd_info[di]->sizes.bp_block,		    dasd_info[di]->sizes.bp_sector);	switch (dasd_info[di]->type) {#ifdef CONFIG_DASD_ECKD	case dasd_eckd:		dasd_info[di]->sizes.label_block = 2;		break;#endif				/* CONFIG_DASD_ECKD */#ifdef CONFIG_DASD_MDSK	case dasd_mdsk:		dasd_info[di]->sizes.label_block = -1;		break;#endif				/* CONFIG_DASD_ECKD */	default:		INTERNAL_CHECK ("Unknown dasd type %d\n", dasd_info[di]->type);	}	minor = di << PARTN_BITS;	dasd_blks[minor] = dasd_info[di]->sizes.kbytes;	dasd_secsize[minor] = dasd_info[di]->sizes.bp_sector;	dasd_blksize[minor] = dasd_info[di]->sizes.bp_block;	dasd_maxsecs[minor] = 252<<dasd_info[di]->sizes.s2b_shift;	dasd_secsize[minor+1] = dasd_info[di]->sizes.bp_sector;	dasd_blksize[minor+1] = dasd_info[di]->sizes.bp_block;	dasd_maxsecs[minor+1] = 252<<dasd_info[di]->sizes.s2b_shift;        {#define DASD_NAME_PREFIX "dasd_"                char * name =  (char *) kmalloc ( 1+strlen (DASD_NAME_PREFIX) +                                                  2 /* 0x */ + 4 /* devno */,                                                  GFP_KERNEL);                sprintf ( name , DASD_NAME_PREFIX "%04x%c",                          dasd_info[di]->info.devno,'\0' );                dasd_info[di] -> devfs_entry =                        devfs_register ( NULL /* dir */,                                         name,                                         DEVFS_FL_DEFAULT /* flags */,                                         DASD_MAJOR, minor,                                         0755 /* mode */,                                          &dasd_device_operations,                                          (void *)dasd_info[di]);        }        /* end of that stuff */ 	return rc;}void dasd_partn_detect ( int di ) {  int  minor = di << PARTN_BITS;  LOOP_CONTROL ("Setting partitions of DASD %d\n", di);  register_disk (&dd_gendisk,                 MKDEV(DASD_MAJOR,minor),                 1 << PARTN_BITS,                 &dasd_device_operations,                 dasd_info[di]->sizes.kbytes << 1);}voiddasd_do_chanq (void){	dasd_chanq_t *qp = NULL;	cqr_t *cqr;        long flags;        int irq;        int tasks;	atomic_set (&bh_scheduled, 0);	dasd_debug (0xc4c40000);	/* DD */	while ((tasks = atomic_read(&chanq_tasks)) != 0) {/* initialization and wraparound */		if (qp == NULL) {			dasd_debug (0xc4c46df0);        /* DD_0 */			qp = cq_head;			if (!qp) {                          dasd_debug (0xc4c46ff1);        /* DD?1 */                          dasd_debug (tasks);                                PRINT_ERR("Mismatch of NULL queue pointer and "                                    "still %d chanq_tasks to do!!\n"                                    "Please send output of /proc/dasd/debug "                                    "to Linux390@de.ibm.com\n", tasks);                          atomic_set(&chanq_tasks,0);                          break;			}		}/* Get first request */		dasd_debug ((unsigned long) qp);		cqr = (cqr_t *) (qp->head);/* empty queue -> dequeue and proceed */		if (!cqr) {			dasd_chanq_t *nqp = qp->next_q;			cql_deq (qp);			qp = nqp;			continue;		}/* process all requests on that queue */		do {			cqr_t *next;			dasd_debug ((unsigned long) cqr);	/* cqr */			if (cqr->magic != DASD_MAGIC) {				dasd_debug (0xc4c46ff2);	/* DD?2 */				panic ( PRINTK_HEADER "do_cq:"					"magic mismatch %p -> %x\n", 					cqr, cqr -> magic);                                break;			}                        irq = dasd_info[cqr->devindex]->info.irq;                        s390irq_spin_lock_irqsave (irq, flags);			switch (atomic_read (&cqr->status)) {			case CQR_STATUS_IN_IO:                                dasd_debug (0xc4c4c9d6);	/* DDIO */                                cqr = NULL;                                break;			case CQR_STATUS_QUEUED:                                dasd_debug (0xc4c4e2e3);	/* DDST */                                if (dasd_start_IO (cqr) == 0) {                                        atomic_dec (&chanq_tasks);                                        cqr = NULL;                                }                                break;			case CQR_STATUS_ERROR:                                dasd_debug (0xc4c4c5d9);	/* DDER */                                dasd_dump_sense (cqr->dstat);                                if ( ++ cqr->retries  < 2 ) {                                        atomic_set (&cqr->status,                                                    CQR_STATUS_QUEUED);	                                dasd_debug (0xc4c4e2e3); /* DDST */                                        if (dasd_start_IO (cqr) == 0) {                                                atomic_dec ( &qp ->                                                              dirty_requests);                                                atomic_dec (&chanq_tasks);                                                cqr = NULL;                                        }                                } else {                                        atomic_set (&cqr->status,                                                    CQR_STATUS_FAILED);                                }                                break;			case CQR_STATUS_DONE:                                next = cqr->next;                                dasd_debug (0xc4c49692);	/* DDok */                                dasd_end_cqr (cqr, 1);                                atomic_dec (&chanq_tasks);                                cqr = next;                                break;			case CQR_STATUS_FAILED:                                next = cqr->next;                                dasd_debug (0xc4c47a7a);	/* DD:: */				if ( ! ( dasd_info[cqr->devindex]-> flags &                                         DASD_INFO_FLAGS_INITIALIZED ) ) {					dasd_info[cqr->devindex]-> flags |=                                                DASD_INFO_FLAGS_INITIALIZED |                                                DASD_INFO_FLAGS_NOT_FORMATTED;				}                                dasd_end_cqr (cqr, 0);                                atomic_dec ( &qp -> dirty_requests );                                atomic_dec (&chanq_tasks);                                cqr = next;                                break;			default:                                PRINT_WARN ("unknown cqrstatus\n");                                cqr = NULL;			}                        s390irq_spin_unlock_irqrestore (irq, flags);		} while (cqr);		qp = qp->next_q;	}	spin_lock (&io_request_lock);	do_dasd_request (&blk_dev[DASD_MAJOR].request_queue);	spin_unlock (&io_request_lock);	dasd_debug (0xc4c46d6d);	/* DD__ */}/*    The request_fn is called from ll_rw_blk for any new request.   We use it to feed the chanqs.   This implementation assumes we are serialized by the io_request_lock. */#define QUEUE_THRESHOLD 5voiddo_dasd_request (request_queue_t *queue){	struct request *req;	cqr_t *cqr;	dasd_chanq_t *q;	long flags;        int di, irq, go;        int broken, busy;        	dasd_debug (0xc4d90000);	/* DR */	dasd_debug ((unsigned long) __builtin_return_address(0));        go = 1;        while (go && !list_empty(&queue->queue_head)) {                req = blkdev_entry_next_request(&queue->queue_head);                req = blkdev_entry_next_request(&queue->queue_head);		di = DEVICE_NR (req->rq_dev);		dasd_debug ((unsigned long) req);	/* req */		dasd_debug (0xc4d90000 +	/* DR## */                            ((((di/16)<9?(di/16)+0xf0:(di/16)+0xc1))<<8) +                            (((di%16)<9?(di%16)+0xf0:(di%16)+0xc1)));                irq = dasd_info[di]->info.irq;                s390irq_spin_lock_irqsave (irq, flags);                q = &dasd_info[di]->queue;                busy = atomic_read(&q->flags) & DASD_CHANQ_BUSY;                broken = atomic_read(&q->flags)&DASD_REQUEST_Q_BROKEN;                if ( ! busy ||                     ( ! broken &&                        (req->nr_sectors >= QUEUE_SECTORS))) {                        blkdev_dequeue_request(req);                        /*                          printk ( KERN_INFO "0x%04x %c %d %d\n",                          req->rq_dev,req->cmd ?'w':'r',                          req->sector,req->nr_sectors);                        */                        cqr = dasd_cqr_from_req (req);                        if (!cqr) {                                dasd_debug (0xc4d96ff1); /* DR?1 */                                dasd_end_request (req, 0);                                goto cont;                        }                        dasd_debug ((unsigned long) cqr);     /* cqr */                        dasd_chanq_enq (q, cqr);                        if (!(atomic_read (&q->flags) &                              DASD_CHANQ_ACTIVE)) {                                cql_enq_head (q);                        }                        if ( ! busy ) {                                atomic_clear_mask (DASD_REQUEST_Q_BROKEN,                                                    &q->flags );                                if (atomic_read( &q->dirty_requests) == 0 ) {                                        if ( dasd_start_IO (cqr) == 0 ) {                                        } else {                                                atomic_inc (&chanq_tasks);                                                schedule_bh (dasd_do_chanq);                                        }                                }                        }                 } else {                        dasd_debug (0xc4d9c2d9);	/* DRBR */                        atomic_set_mask (DASD_REQUEST_Q_BROKEN, &q->flags );                        go = 0;		}        cont:                s390irq_spin_unlock_irqrestore (irq, flags);	}	dasd_debug (0xc4d96d6d);	/* DR__ */}voiddasd_handler (int irq, void *ds, struct pt_regs *regs){	devstat_t *stat = (devstat_t *) ds;	int ip;	cqr_t *cqr;	int done_fast_io = 0;        	dasd_debug (0xc4c80000);	/* DH */	if (!stat)		PRINT_ERR ("handler called without devstat");	ip = stat->intparm;	dasd_debug (ip);	/* intparm */	switch (ip) {		/* filter special intparms... */	case 0x00000000:	/* no intparm: unsolicited interrupt */		dasd_debug (0xc4c8a489);	/* DHui */		PRINT_INFO ("Unsolicited interrupt on device %04X\n",			    stat->devno);		dasd_dump_sense (stat);		return;	default:		if (ip & 0x80000001) {			dasd_debug (0xc4c8a489);	/* DHui */			PRINT_INFO ("Spurious interrupt %08x on device %04X\n",				    ip, stat->devno);			return;		}		cqr = (cqr_t *) ip;		if (cqr->magic != DASD_MAGIC) {			dasd_debug (0xc4c86ff1);	/* DH?1 */			PRINT_ERR ("handler:magic mismatch on %p %08x\n",                                   cqr, cqr->magic);

⌨️ 快捷键说明

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