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

📄 dasd.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
dasd_device_from_kdev (kdev_t kdev){	major_info_t *major_info = NULL;	struct list_head *l;	unsigned long flags;	spin_lock_irqsave (&dasd_major_lock, flags);	list_for_each (l, &dasd_major_info[0].list) {		major_info = list_entry (l, major_info_t, list);		if (major_info->gendisk.major == MAJOR (kdev))			break;	}	spin_unlock_irqrestore (&dasd_major_lock, flags);	if (major_info != &dasd_major_info[0])		return major_info->dasd_device[MINOR (kdev) >> DASD_PARTN_BITS];	return NULL;}/* * function: dasd_device_from_devno * finds the address of the device structure corresponding to the devno * supplied as argument in the major_info structures and returns * it or NULL when not found */static inline dasd_device_t **dasd_device_from_devno (int devno){	major_info_t *major_info;	struct list_head *l;	int devindex = dasd_devindex_from_devno (devno);	unsigned long flags;	spin_lock_irqsave (&dasd_major_lock, flags);	list_for_each (l, &dasd_major_info[0].list) {		major_info = list_entry (l, major_info_t, list);		if (devindex < DASD_PER_MAJOR) {			spin_unlock_irqrestore (&dasd_major_lock, flags);			return &major_info->dasd_device[devindex];		}		devindex -= DASD_PER_MAJOR;	}	spin_unlock_irqrestore (&dasd_major_lock, flags);	return NULL;}/* * function: dasd_features_from_devno * finds the device range corresponding to the devno * supplied as argument in the major_info structures and returns * the features set for it */static intdasd_features_from_devno (int devno){	dasd_range_t *temp;	int devindex = 0;	unsigned long flags;	struct list_head *l;	spin_lock_irqsave (&range_lock, flags);	list_for_each (l, &dasd_range_head.list) {		temp = list_entry (l, dasd_range_t, list);		if (devno >= temp->from && devno <= temp->to) {			spin_unlock_irqrestore (&range_lock, flags);			return temp->features;		}		devindex += temp->to - temp->from + 1;	}	spin_unlock_irqrestore (&range_lock, flags);	return -ENODEV;}/* SECTION: managing dasd disciplines *//* anchor and spinlock for list of disciplines */static struct list_head dasd_disc_head = LIST_HEAD_INIT(dasd_disc_head);static spinlock_t discipline_lock = SPIN_LOCK_UNLOCKED;/* * function dasd_discipline_enq * chains the discpline given as argument to the head of disiplines * head chaining policy is required to allow module disciplines to * be preferred against those, who are statically linked */static inline voiddasd_discipline_enq (dasd_discipline_t * d){    list_add(&d->list, &dasd_disc_head);}/* * function dasd_discipline_deq * removes the discipline given as argument from the list of disciplines */static inline voiddasd_discipline_deq (dasd_discipline_t * d){        list_del(&d->list);}voiddasd_discipline_add (dasd_discipline_t * d){        unsigned long flags;        MOD_INC_USE_COUNT;	spin_lock_irqsave (&discipline_lock,flags);        dasd_discipline_enq (d);	spin_unlock_irqrestore (&discipline_lock,flags);        dasd_enable_ranges (&dasd_range_head, d, DASD_STATE_ONLINE);}void dasd_discipline_del (dasd_discipline_t * d){        unsigned long flags;	spin_lock_irqsave (&discipline_lock,flags);        dasd_disable_ranges(&dasd_range_head, d, DASD_STATE_DEL, 1);        dasd_discipline_deq (d);	spin_unlock_irqrestore (&discipline_lock,flags);        MOD_DEC_USE_COUNT;}static inline dasd_discipline_t *dasd_find_disc (dasd_device_t * device, dasd_discipline_t *d){        dasd_discipline_t *t;        struct list_head *l = d ? &d->list : dasd_disc_head.next;        do {                t = list_entry(l,dasd_discipline_t,list);                if ( ( t->id_check == NULL ||                       t->id_check (&device->devinfo) == 0 ) &&                     ( t->check_characteristics == NULL ||                       t->check_characteristics (device) == 0 ) )                        break;                l = l->next;                if ( d ||                      l == &dasd_disc_head ) {                        t = NULL;                        break;                }         } while ( 1 );	return t;}/* SECTION: profiling stuff */static dasd_profile_info_t dasd_global_profile;#ifdef DASD_PROFILE/* * macro: dasd_profile_add_counter * increments counter in global and local profiling structures * according to the value */#define dasd_profile_add_counter( value, counter, device ) \{ \        int ind; \        long help; \	for (ind = 0, help = value >> 3; \             ind < 31 && help; \             help = help >> 1, ind++) {} \	dasd_global_profile.counter[ind]++; \        device->profile.counter[ind]++; \}/* * function dasd_profile_add * adds the profiling information from the cqr given as argument to the * global and device specific profiling information */voiddasd_profile_add (ccw_req_t * cqr){	long strtime, irqtime, endtime, tottime; /* in microsecnds*/	long tottimeps, sectors;	dasd_device_t *device = cqr->device;	if (!cqr->req)		/* safeguard against abnormal cqrs */		return;        if ((!cqr->buildclk) ||            (!cqr->startclk) ||            (!cqr->stopclk ) ||            (!cqr->endclk  ) ||            (!(sectors = ((struct request *) (cqr->req))->nr_sectors)))                return;	strtime = ((cqr->startclk - cqr->buildclk) >> 12);	irqtime = ((cqr->stopclk - cqr->startclk) >> 12);	endtime = ((cqr->endclk - cqr->stopclk) >> 12);	tottime = ((cqr->endclk - cqr->buildclk) >> 12);	tottimeps = tottime / sectors;	if (!dasd_global_profile.dasd_io_reqs) {		memset (&dasd_global_profile, 0, sizeof (dasd_profile_info_t));	};	if (!device->profile.dasd_io_reqs) {		memset (&device->profile, 0, sizeof (dasd_profile_info_t));	};	dasd_global_profile.dasd_io_reqs++;	device->profile.dasd_io_reqs++;	dasd_global_profile.dasd_io_sects+=sectors;	device->profile.dasd_io_sects+=sectors;	dasd_profile_add_counter (sectors, dasd_io_secs, device);	dasd_profile_add_counter (tottime, dasd_io_times, device);	dasd_profile_add_counter (tottimeps, dasd_io_timps, device);	dasd_profile_add_counter (strtime, dasd_io_time1, device);	dasd_profile_add_counter (irqtime, dasd_io_time2, device);	dasd_profile_add_counter (irqtime / sectors, dasd_io_time2ps, device);	dasd_profile_add_counter (endtime, dasd_io_time3, device);}#endif/* SECTION: All the gendisk stuff *//* SECTION: Managing wrappers for ccwcache *//* * function dasd_alloc_request * tries to return space for a channel program of length cplength with * additional data of size datasize. * If the ccwcache cannot fulfill the request it tries the emergeny requests * before giving up finally * FIXME: initialization of ccw_req_t should be done by function of ccwcache */ccw_req_t *dasd_alloc_request (char *magic, int cplength, int datasize, dasd_device_t* device){	ccw_req_t *rv = NULL;	if ((rv = ccw_alloc_request (magic, cplength, datasize)) != NULL) {		return rv;	}	if ((((sizeof (ccw_req_t) + 7) & -8) +	     cplength * sizeof (ccw1_t) + datasize) > PAGE_SIZE) {		BUG ();		}        if (device->lowmem_cqr==NULL) {                DASD_DRIVER_DEBUG_EVENT (2, dasd_alloc_request,                                         "(%04x) Low memory! Using emergency request %p.",                                         device->devinfo.devno,                                         device->lowmem_ccws);                device->lowmem_cqr=device->lowmem_ccws;                rv = device->lowmem_ccws;		memset (rv, 0, PAGE_SIZE);		strncpy ((char *) (&rv->magic), magic, 4);		ASCEBC ((char *) (&rv->magic), 4);		rv->cplength = cplength;		rv->datasize = datasize;		rv->data = (void *) ((long) rv + PAGE_SIZE - datasize);		rv->cpaddr = (ccw1_t *) ((long) rv + sizeof (ccw_req_t));        } else {                DASD_DRIVER_DEBUG_EVENT (2, dasd_alloc_request,                                         "(%04x) Refusing emergency mem for request "                                         "NULL, already in use at %p.",                                         device->devinfo.devno,                                         device->lowmem_ccws);	}	return rv;}/* * function dasd_free_request * returns a ccw_req_t to the appropriate cache or emergeny request line */voiddasd_free_request (ccw_req_t * request, dasd_device_t* device){#ifdef CONFIG_ARCH_S390X        ccw1_t* ccw;        /* clear any idals used for chain */        ccw=request->cpaddr-1;        do {                ccw++;                if ((ccw->cda < (unsigned long) device->lowmem_idals           ) ||                     (ccw->cda >= (unsigned long) device->lowmem_idals+PAGE_SIZE)   )                        clear_normalized_cda (ccw);                else {                        if (device->lowmem_idal_ptr != device->lowmem_idals)                                DASD_MESSAGE (KERN_WARNING, device,                                              "Freeing emergency idals from request at %p.",                                              request);                        device->lowmem_idal_ptr = device->lowmem_idals;                        device->lowmem_cqr=NULL;                }        } while ((ccw->flags & CCW_FLAG_CC) ||                  (ccw->flags & CCW_FLAG_DC)   );#endif        if (request != device->lowmem_ccws) {                 /* compare to lowmem_ccws to protect usage of lowmem_cqr for IDAL only ! */		ccw_free_request (request);        } else {                DASD_MESSAGE (KERN_WARNING, device,                              "Freeing emergency request at %p",                              request);                device->lowmem_cqr=NULL;	}}intdasd_set_normalized_cda (ccw1_t * cp, unsigned long address,                          ccw_req_t* request, dasd_device_t* device ){#ifdef CONFIG_ARCH_S390X	int nridaws;        int count = cp->count;                if (set_normalized_cda (cp, address)!=-ENOMEM) {                return 0;        }        if ((device->lowmem_cqr!=NULL) && (device->lowmem_cqr!=request)) {                DASD_MESSAGE (KERN_WARNING, device,                               "Refusing emergency idals for request %p, memory"                              " is already in use for request %p",                              request,                              device->lowmem_cqr);                return -ENOMEM;        }        device->lowmem_cqr=request;        if (device->lowmem_idal_ptr == device->lowmem_idals) {            DASD_MESSAGE (KERN_WARNING,device,                           "Low memory! Using emergency IDALs for request %p.\n",                          request);        }        nridaws = ((address & (IDA_BLOCK_SIZE-1)) + count + 		   (IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG;	if ( device->lowmem_idal_ptr>=device->lowmem_idals + PAGE_SIZE ) {		/* Ouch! No Idals left for emergency request */		BUG();	}	cp->flags |= CCW_FLAG_IDA;	cp->cda = (__u32)(unsigned long)device->lowmem_idal_ptr;        do {		*((long*)device->lowmem_idal_ptr) = address;		address = (address & -(IDA_BLOCK_SIZE)) + (IDA_BLOCK_SIZE);		nridaws --;                device->lowmem_idal_ptr += sizeof(unsigned long);        } while ( nridaws > 0 );#else         cp -> cda = address;#endif	return 0;}/* SECTION: (de)queueing of requests to channel program queues *//* * function dasd_chanq_enq * appends the cqr given as argument to the queue * has to be called with the queue lock (namely the s390_irq_lock) acquired */inline voiddasd_chanq_enq (dasd_chanq_t * q, ccw_req_t * cqr){	if (q->head != NULL) {		q->tail->next = cqr;	} else		q->head = cqr;	cqr->next = NULL;	q->tail = cqr;	check_then_set (&cqr->status,                         CQR_STATUS_FILLED,                         CQR_STATUS_QUEUED);       #ifdef DASD_PROFILE        /* save profile information for non erp cqr */        if (cqr->refers == NULL) {                unsigned int  counter = 0;                ccw_req_t     *ptr;                dasd_device_t *device = cqr->device;                /* count the length of the chanq for statistics */                for (ptr = q->head;                      ptr->next != NULL && counter <=31;                      ptr = ptr->next) {                        counter++;                }                                                dasd_global_profile.dasd_io_nr_req[counter]++;                device->profile.dasd_io_nr_req[counter]++;        }#endif }/* * function dasd_chanq_enq_head * chains the cqr given as argument to the queue head * has to be called with the queue lock (namely the s390_irq_lock) acquired */inline voiddasd_chanq_enq_head (dasd_chanq_t * q, ccw_req_t * cqr){	cqr->next = q->head;	q->head = cqr;	if (q->tail == NULL)		q->tail = cqr;	check_then_set (&cqr->status, CQR_STATUS_FILLED, CQR_STATUS_QUEUED);}/* * function dasd_chanq_deq * dechains the cqr given as argument from the queue * has to be called with the queue lock (namely the s390_irq_lock) acquired */inline voiddasd_chanq_deq (dasd_chanq_t * q, ccw_req_t * cqr){	ccw_req_t *prev;	if (cqr == NULL)		BUG ();	if (cqr == q->head) {		q->head = cqr->next;		if (q->head == NULL)			q->tail = NULL;	} else {		prev = q->head;		while (prev && prev->next != cqr)			prev = prev->next;		if (prev == NULL)			return;		prev->next = cqr->next;		if (prev->next == NULL)			q->tail = prev;	}	cqr->next = NULL;}

⌨️ 快捷键说明

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