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

📄 tape.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 3 页
字号:
                            debug_int_exception (tape_debug_area,3,rc);#endif /* TAPE_DEBUG */                            kfree (ti);                        } else {                            s390irq_spin_lock_irqsave (irq, lockflags);                            if (first_tape_info == NULL) {                                first_tape_info = ti;                            } else {                                tempti = first_tape_info;                                while (tempti->next != NULL)                                    tempti = tempti->next;                                tempti->next = ti;                            }                            s390irq_spin_unlock_irqrestore (irq, lockflags);                        }                    }                    tape_num+=2;                }                str++;        }}/* SECTION: Managing wrappers for ccwcache */#define TAPE_EMERGENCY_REQUESTS 16static ccw_req_t *tape_emergency_req[TAPE_EMERGENCY_REQUESTS] ={NULL,};static spinlock_t tape_emergency_req_lock = SPIN_LOCK_UNLOCKED;static voidtape_init_emergency_req (void){	int i;	for (i = 0; i < TAPE_EMERGENCY_REQUESTS; i++) {		tape_emergency_req[i] = (ccw_req_t *) get_free_page (GFP_KERNEL);	}}#ifdef MODULE // We only cleanup the emergency requests on module unload.static voidtape_cleanup_emergency_req (void){	int i;	for (i = 0; i < TAPE_EMERGENCY_REQUESTS; i++) {		if (tape_emergency_req[i])			free_page ((long) (tape_emergency_req[i]));		else			printk (KERN_WARNING PRINTK_HEADER "losing one page for 'in-use' emergency request\n");	}}#endifccw_req_t *tape_alloc_request (char *magic, int cplength, int datasize){	ccw_req_t *rv = NULL;	int i;	if ((rv = ccw_alloc_request (magic, cplength, datasize)) != NULL) {		return rv;	}	if (cplength * sizeof (ccw1_t) + datasize + sizeof (ccw_req_t) > PAGE_SIZE) {		return NULL;	}	spin_lock (&tape_emergency_req_lock);	for (i = 0; i < TAPE_EMERGENCY_REQUESTS; i++) {		if (tape_emergency_req[i] != NULL) {			rv = tape_emergency_req[i];			tape_emergency_req[i] = NULL;		}	}	spin_unlock (&tape_emergency_req_lock);	if (rv) {		memset (rv, 0, PAGE_SIZE);		rv->cache = (kmem_cache_t *) (tape_emergency_req + i);		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));	}	return rv;}voidtape_free_request (ccw_req_t * request){	if (request->cache >= (kmem_cache_t *) tape_emergency_req &&	    request->cache <= (kmem_cache_t *) (tape_emergency_req + TAPE_EMERGENCY_REQUESTS)) {		*((ccw_req_t **) (request->cache)) = request;	} else {		clear_normalized_cda ((ccw1_t *) (request->cpaddr));	// avoid memory leak caused by modeset_byte		ccw_free_request (request);	}}/* * Allocate a ccw request and reserve it for tape driver */inline ccw_req_t *tape_alloc_ccw_req (tape_info_t * ti, int cplength, int datasize){	char tape_magic_id[] = "tape";	ccw_req_t *cqr = NULL;	if (!ti)		return NULL;	cqr = tape_alloc_request (tape_magic_id, cplength, datasize);	if (!cqr) {#ifdef TAPE_DEBUG		PRINT_WARN ("empty CQR generated\n");#endif	}	cqr->magic = TAPE_MAGIC;	/* sets an identifier for tape driver   */	cqr->device = ti;	/* save pointer to tape info    */	return cqr;}/* * Find the tape_info_t structure associated with irq */static inline tape_info_t *tapedev_find_info (int irq){	tape_info_t *ti;	ti = first_tape_info;	if (ti != NULL)		do {			if (ti->devinfo.irq == irq)				break;		} while ((ti = (tape_info_t *) ti->next) != NULL);	return ti;}#define QUEUE_THRESHOLD 5/* * Tape interrupt routine, called from Ingo's I/O layer */voidtape_irq (int irq, void *int_parm, struct pt_regs *regs){	tape_info_t *ti = tapedev_find_info (irq);	/* analyse devstat and fire event */	if (ti->devstat.dstat & DEV_STAT_UNIT_CHECK) {		tapestate_event (ti, TE_ERROR);	} else if (ti->devstat.dstat & (DEV_STAT_DEV_END)) {		tapestate_event (ti, TE_DONE);	} else		tapestate_event (ti, TE_OTHER);}int tape_oper_handler ( int irq, struct _devreg *dreg) {    tape_info_t* ti=first_tape_info;    tape_info_t* newtape;    int rc,tape_num,retries=0,i;    s390_dev_info_t dinfo;    tape_discipline_t* disc;#ifdef CONFIG_DEVFS_FS    tape_frontend_t* frontend;#endif    long lockflags;    while ((ti!=NULL) && (ti->devinfo.irq!=irq))         ti=ti->next;    if (ti!=NULL) {        // irq is (still) used by tape. tell ingo to try again later        PRINT_WARN ("Oper handler for irq %d called while irq still (internaly?) used.\n",irq);        return -EAGAIN;    }    // irq is not used by tape    rc = get_dev_info_by_irq (irq, &dinfo);    if (rc == -ENODEV) {        retries++;        rc = get_dev_info_by_irq (irq, &dinfo);        if (retries > 5) {            PRINT_WARN ("No device information for new dev. could be retrieved.\n");            return -ENODEV;        }    }    disc = first_discipline;    while ((disc != NULL) && (disc->cu_type != dinfo.sid_data.cu_type))        disc = (tape_discipline_t *) (disc->next);    if (disc == NULL)        PRINT_WARN ("No matching discipline for cu_type %x found, ignoring device %04x.\n",dinfo.sid_data.cu_type,dinfo.devno);    if (rc == -ENODEV)         PRINT_WARN ("No device information for new dev. could be retrieved.\n");    if ((disc == NULL) || (rc == -ENODEV))        return -ENODEV;        /* Allocate tape structure  */    ti = kmalloc (sizeof (tape_info_t), GFP_ATOMIC);    if (ti == NULL) {        PRINT_INFO ( "tape: can't allocate memory for "                    "tape info structure\n");        return -ENOBUFS;    }    memset(ti,0,sizeof(tape_info_t));    ti->discipline = disc;    disc->tape = ti;    tape_num=0;    if (*tape) {        // we have static device ranges, so fingure out the tape_num of the attached tape        for (i=0;i<devregct;i++)            if (tape_devreg[i]->ci.devno==dinfo.devno) {                tape_num=2*i;                break;            }    } else {        // we are running in autoprobe mode, find a free tape_num        newtape=first_tape_info;        while (newtape!=NULL) {            if (newtape->rew_minor==tape_num) {                // tape num in use. try next one                tape_num+=2;                newtape=first_tape_info;            } else {                // tape num not used by newtape. look at next tape info                newtape=newtape->next;            }        }    }    rc = tape_setup (ti, irq, tape_num);    if (rc) {        kfree (ti);        return -ENOBUFS;    }#ifdef CONFIG_DEVFS_FS    for (frontend=first_frontend;frontend!=NULL;frontend=frontend->next)         frontend->mkdevfstree(ti);#endif    s390irq_spin_lock_irqsave (irq,lockflags);    if (first_tape_info == NULL) {        first_tape_info = ti;    } else {        newtape = first_tape_info;        while (newtape->next != NULL)            newtape = newtape->next;        newtape->next = ti;    }    s390irq_spin_unlock_irqrestore (irq, lockflags);    return 0;}static voidtape_noper_handler ( int irq, int status ) {    tape_info_t *ti=first_tape_info;    tape_info_t *lastti;#ifdef CONFIG_DEVFS_FS    tape_frontend_t *frontend;#endif    long lockflags;    s390irq_spin_lock_irqsave(irq,lockflags);    while (ti!=NULL && ti->devinfo.irq!=irq) ti=ti->next;    if (ti==NULL) return;    if (tapestate_get(ti)!=TS_UNUSED) {        // device is in use!        PRINT_WARN ("Tape #%d was detached while it was busy. Expect errors!",ti->blk_minor/2);        tapestate_set(ti,TS_NOT_OPER);        ti->rc=-ENODEV; 	ti->wanna_wakeup=1;	switch (tapestate_get(ti)) {	case TS_REW_RELEASE_INIT:	    tapestate_set(ti,TS_NOT_OPER);	    wake_up (&ti->wq);	    break;#ifdef CONFIG_S390_TAPE_BLOCK	case TS_BLOCK_INIT:	    tapestate_set(ti,TS_NOT_OPER);	    schedule_tapeblock_exec_IO(ti);	    break;#endif	default:	    tapestate_set(ti,TS_NOT_OPER);	    wake_up_interruptible (&ti->wq);	}    } else {        // device is unused!        PRINT_WARN ("Tape #%d was detached.\n",ti->blk_minor/2);        if (ti==first_tape_info) {            first_tape_info=ti->next;        } else {            lastti=first_tape_info;            while (lastti->next!=ti) lastti=lastti->next;            lastti->next=ti->next;        }#ifdef CONFIG_DEVFS_FS        for (frontend=first_frontend;frontend!=NULL;frontend=frontend->next)            frontend->rmdevfstree(ti);        tape_rmdevfsroots(ti);#endif        kfree(ti);    }    s390irq_spin_unlock_irqrestore(irq,lockflags);    return;}voidtape_dump_sense (devstat_t * stat){#ifdef TAPE_DEBUG        int sl;#endif#if 0	PRINT_WARN ("------------I/O resulted in unit check:-----------\n");	for (sl = 0; sl < 4; sl++) {		PRINT_WARN ("Sense:");		for (sct = 0; sct < 8; sct++) {			PRINT_WARN (" %2d:0x%02X", 8 * sl + sct,				    stat->ii.sense.data[8 * sl + sct]);		}		PRINT_WARN ("\n");	}	PRINT_INFO ("Sense data: %02X%02X%02X%02X %02X%02X%02X%02X "		    " %02X%02X%02X%02X %02X%02X%02X%02X \n",		    stat->ii.sense.data[0], stat->ii.sense.data[1],		    stat->ii.sense.data[2], stat->ii.sense.data[3],		    stat->ii.sense.data[4], stat->ii.sense.data[5],		    stat->ii.sense.data[6], stat->ii.sense.data[7],		    stat->ii.sense.data[8], stat->ii.sense.data[9],		    stat->ii.sense.data[10], stat->ii.sense.data[11],		    stat->ii.sense.data[12], stat->ii.sense.data[13],		    stat->ii.sense.data[14], stat->ii.sense.data[15]);	PRINT_INFO ("Sense data: %02X%02X%02X%02X %02X%02X%02X%02X "		    " %02X%02X%02X%02X %02X%02X%02X%02X \n",		    stat->ii.sense.data[16], stat->ii.sense.data[17],		    stat->ii.sense.data[18], stat->ii.sense.data[19],		    stat->ii.sense.data[20], stat->ii.sense.data[21],		    stat->ii.sense.data[22], stat->ii.sense.data[23],		    stat->ii.sense.data[24], stat->ii.sense.data[25],		    stat->ii.sense.data[26], stat->ii.sense.data[27],		    stat->ii.sense.data[28], stat->ii.sense.data[29],		    stat->ii.sense.data[30], stat->ii.sense.data[31]);#endif#ifdef TAPE_DEBUG        debug_text_event (tape_debug_area,3,"SENSE:");        for (sl=0;sl<31;sl++) {            debug_int_event (tape_debug_area,3,stat->ii.sense.data[sl]);        }        debug_int_exception (tape_debug_area,3,stat->ii.sense.data[31]);#endif}/* * Setup tape_info_t structure of a tape device */inttape_setup (tape_info_t * ti, int irq, int minor){	long lockflags;	int rc = 0;        if (minor>254) {            PRINT_WARN ("Device id %d on irq %d will not be accessible since this driver is restricted to 128 devices.\n",minor/2,irq);            return -EINVAL;        }	rc = get_dev_info_by_irq (irq, &(ti->devinfo));	if (rc == -ENODEV) {	/* end of device list */		return rc;	}	ti->rew_minor = minor;	ti->nor_minor = minor + 1;	ti->blk_minor = minor;#ifdef CONFIG_DEVFS_FS        tape_mkdevfsroots(ti);

⌨️ 快捷键说明

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