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

📄 aha152x.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  Abort a command * */int aha152x_abort(Scsi_Cmnd *SCpnt){	struct Scsi_Host *shpnt = SCpnt->host;	Scsi_Cmnd *ptr;	unsigned long flags;	if(!shpnt) {		printk(ERR_LEAD "abort(%p): no host structure\n", CMDINFO(SCpnt), SCpnt);		return FAILED;	}#if defined(AHA152X_DEBUG)	if(HOSTDATA(shpnt)->debug & debug_eh) {		printk(DEBUG_LEAD "abort(%p)", CMDINFO(SCpnt), SCpnt);		show_queues(shpnt);		mdelay(1000);	}#endif	DO_LOCK(flags);	ptr=remove_SC(&ISSUE_SC, SCpnt);	if(ptr) {		DPRINTK(debug_eh, DEBUG_LEAD "not yet issued - SUCCESS\n", CMDINFO(SCpnt));		HOSTDATA(shpnt)->commands--;		if (!HOSTDATA(shpnt)->commands)			SETPORT(PORTA, 0);		DO_UNLOCK(flags);		kfree(SCpnt->host_scribble);		SCpnt->host_scribble=0;		return SUCCESS;	} 	DO_UNLOCK(flags);	/*	 * FIXME:	 * for current command: queue ABORT for message out and raise ATN	 * for disconnected command: pseudo SC with ABORT message or ABORT on reselection?	 *	 */	printk(ERR_LEAD "cannot abort running or disconnected command\n", CMDINFO(SCpnt));	return FAILED;}static void timer_expired(unsigned long p){	struct semaphore *sem = (void *)p;	printk(KERN_INFO "aha152x: timer expired\n");	up(sem);}/* * Reset a device * * FIXME: never seen this live. might lockup... * */int aha152x_device_reset(Scsi_Cmnd * SCpnt){	struct Scsi_Host *shpnt = SCpnt->host;	DECLARE_MUTEX_LOCKED(sem);	struct timer_list timer;	Scsi_Cmnd cmnd;#if defined(AHA152X_DEBUG)	if(HOSTDATA(shpnt)->debug & debug_eh) {		printk(INFO_LEAD "aha152x_device_reset(%p)", CMDINFO(SCpnt), SCpnt);		show_queues(shpnt);		mdelay(1000);	}#endif	if(CURRENT_SC==SCpnt) {		printk(ERR_LEAD "cannot reset current device\n", CMDINFO(SCpnt));		return FAILED;	}	cmnd.cmd_len         = 0;	cmnd.host            = SCpnt->host;	cmnd.target          = SCpnt->target;	cmnd.lun             = SCpnt->lun;	cmnd.use_sg          = 0;	cmnd.request_buffer  = 0;	cmnd.request_bufflen = 0;	init_timer(&timer);	timer.data     = (unsigned long) &sem;	timer.expires  = jiffies + 10 * HZ;   /* 10s */	timer.function = (void (*)(unsigned long)) timer_expired;	add_timer(&timer);	aha152x_internal_queue(&cmnd, &sem, resetting, 0, internal_done);	down(&sem);	del_timer(&timer);	if(cmnd.SCp.phase & resetted) {		return SUCCESS;	} else {		return FAILED;	}}void free_hard_reset_SCs(struct Scsi_Host *shpnt, Scsi_Cmnd **SCs){	Scsi_Cmnd *ptr;	unsigned long flags;	DO_LOCK(flags);	ptr=*SCs;	while(ptr) {		Scsi_Cmnd *next = SCNEXT(ptr);		if (!ptr->device->soft_reset) {			DPRINTK(debug_eh, DEBUG_LEAD "disconnected command %p removed\n", CMDINFO(ptr), ptr);			remove_SC(SCs, ptr);			HOSTDATA(shpnt)->commands--;			kfree(ptr->host_scribble);			ptr->host_scribble=0;		}		ptr = next;	}	DO_UNLOCK(flags);}/* * Reset the bus * */int aha152x_bus_reset(Scsi_Cmnd *SCpnt){	struct Scsi_Host *shpnt = SCpnt->host;	unsigned long flags;#if defined(AHA152X_DEBUG)	if(HOSTDATA(shpnt)->debug & debug_eh) {		printk(DEBUG_LEAD "aha152x_bus_reset(%p)", CMDINFO(SCpnt), SCpnt);		show_queues(shpnt);		mdelay(1000);	}#endif	free_hard_reset_SCs(shpnt, &ISSUE_SC);	free_hard_reset_SCs(shpnt, &DISCONNECTED_SC);	DPRINTK(debug_eh, DEBUG_LEAD "resetting bus\n", CMDINFO(SCpnt));	SETPORT(SCSISEQ, SCSIRSTO);	mdelay(256);	SETPORT(SCSISEQ, 0);	mdelay(DELAY);	DPRINTK(debug_eh, DEBUG_LEAD "bus reset returns\n", CMDINFO(SCpnt));	DO_LOCK(flags);	setup_expected_interrupts(shpnt);	if(HOSTDATA(shpnt)->commands==0)		SETPORT(PORTA, 0);	DO_UNLOCK(flags);	return SUCCESS;}/* *  Restore default values to the AIC-6260 registers and reset the fifos * */static void reset_ports(struct Scsi_Host *shpnt){	unsigned long flags;	/* disable interrupts */	SETPORT(DMACNTRL0, RSTFIFO);	SETPORT(SCSISEQ, 0);	SETPORT(SXFRCTL1, 0);	SETPORT(SCSISIG, 0);	SETRATE(0);	/* clear all interrupt conditions */	SETPORT(SSTAT0, 0x7f);	SETPORT(SSTAT1, 0xef);	SETPORT(SSTAT4, SYNCERR | FWERR | FRERR);	SETPORT(DMACNTRL0, 0);	SETPORT(DMACNTRL1, 0);	SETPORT(BRSTCNTRL, 0xf1);	/* clear SCSI fifos and transfer count */	SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT);	SETPORT(SXFRCTL0, CH1);	DO_LOCK(flags);	setup_expected_interrupts(shpnt);	DO_UNLOCK(flags);}/* * Reset the host (bus and controller) * */int aha152x_host_reset(Scsi_Cmnd * SCpnt){#if defined(AHA152X_DEBUG)	struct Scsi_Host *shpnt = SCpnt->host;#endif	DPRINTK(debug_eh, DEBUG_LEAD "aha152x_host_reset(%p)\n", CMDINFO(SCpnt), SCpnt);	aha152x_bus_reset(SCpnt);	DPRINTK(debug_eh, DEBUG_LEAD "resetting ports\n", CMDINFO(SCpnt));	reset_ports(SCpnt->host);	return SUCCESS;}/* * Return the "logical geometry" * */int aha152x_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array){	struct Scsi_Host *shpnt = disk->device->host;	/* try default translation */	info_array[0] = 64;	info_array[1] = 32;	info_array[2] = disk->capacity / (64 * 32);	/* for disks >1GB do some guessing */	if (info_array[2] >= 1024) {		int info[3];		/* try to figure out the geometry from the partition table */		if (scsicam_bios_param(disk, dev, info) < 0 ||		    !((info[0] == 64 && info[1] == 32) || (info[0] == 255 && info[1] == 63))) {			if (EXT_TRANS) {				printk(KERN_NOTICE				       "aha152x: unable to verify geometry for disk with >1GB.\n"				       "         using extended translation.\n");				info_array[0] = 255;				info_array[1] = 63;				info_array[2] = disk->capacity / (255 * 63);			} else {				printk(KERN_NOTICE				       "aha152x: unable to verify geometry for disk with >1GB.\n"				       "         Using default translation. Please verify yourself.\n"				       "         Perhaps you need to enable extended translation in the driver.\n"				       "         See /usr/src/linux/drivers/scsi/README.aha152x for details.\n");			}		} else {			info_array[0] = info[0];			info_array[1] = info[1];			info_array[2] = info[2];			if (info[0] == 255 && !EXT_TRANS) {				printk(KERN_NOTICE				       "aha152x: current partition table is using extended translation.\n"				       "         using it also, although it's not explictly enabled.\n");			}		}	}	return 0;}/* *  Internal done function * */static void done(struct Scsi_Host *shpnt, int error){	if (CURRENT_SC) {		if(DONE_SC)			printk(ERR_LEAD "there's already a completed command %p - will cause abort\n", CMDINFO(CURRENT_SC), DONE_SC);		DONE_SC = CURRENT_SC;		CURRENT_SC = 0;		DONE_SC->result = error;	} else		printk(KERN_ERR "aha152x: done() called outside of command\n");}static struct tq_struct aha152x_tq;/* * Run service completions on the card with interrupts enabled. * */static void run(void){	int i;	for (i = 0; i < IRQS; i++) {		struct Scsi_Host *shpnt = aha152x_host[i];		if (shpnt && HOSTDATA(shpnt)->service) {			HOSTDATA(shpnt)->service=0;			complete(shpnt);		}	}}/* *    Interrupts handler * */static void intr(int irqno, void *dev_id, struct pt_regs *regs){	struct Scsi_Host *shpnt = aha152x_host[irqno - IRQ_MIN];	if (!shpnt) {		printk(KERN_ERR "aha152x: catched interrupt for unknown controller.\n");		return;	}	/* no more interrupts from the controller, while we're busy.	   INTEN is restored by the BH handler */	CLRBITS(DMACNTRL0, INTEN);#if 0	/* check if there is already something to be           serviced; should not happen */	if(HOSTDATA(shpnt)->service) {		printk(KERN_ERR "aha152x%d: lost interrupt (%d)\n", HOSTNO, HOSTDATA(shpnt)->service);	        show_queues(shpnt);	}#endif		/* Poke the BH handler */	HOSTDATA(shpnt)->service++;	aha152x_tq.routine = (void *) run;	queue_task(&aha152x_tq, &tq_immediate);	mark_bh(IMMEDIATE_BH);}/* * busfree phase * - handle completition/disconnection/error of current command * - start selection for next command (if any) */static void busfree_run(struct Scsi_Host *shpnt){	unsigned long flags;#if defined(AHA152X_STAT)	int action=0;#endif	SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT);	SETPORT(SXFRCTL0, CH1);	SETPORT(SSTAT1, CLRBUSFREE);		if(CURRENT_SC) {#if defined(AHA152X_STAT)		action++;#endif		CURRENT_SC->SCp.phase &= ~syncneg;		if(CURRENT_SC->SCp.phase & completed) {			/* target sent COMMAND COMPLETE */			done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16));		} else if(CURRENT_SC->SCp.phase & aborted) {			DPRINTK(debug_eh, DEBUG_LEAD "ABORT sent\n", CMDINFO(CURRENT_SC));			done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_ABORT << 16));		} else if(CURRENT_SC->SCp.phase & resetted) {			DPRINTK(debug_eh, DEBUG_LEAD "BUS DEVICE RESET sent\n", CMDINFO(CURRENT_SC));			done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_RESET << 16));		} else if(CURRENT_SC->SCp.phase & disconnected) {			/* target sent DISCONNECT */			DPRINTK(debug_selection, DEBUG_LEAD "target disconnected at %d/%d\n",				CMDINFO(CURRENT_SC),				CURRENT_SC->resid,				CURRENT_SC->request_bufflen);#if defined(AHA152X_STAT)			HOSTDATA(shpnt)->disconnections++;#endif			append_SC(&DISCONNECTED_SC, CURRENT_SC);			CURRENT_SC->SCp.phase |= 1 << 16;			CURRENT_SC = 0;		} else {			done(shpnt, DID_ERROR << 16);		}#if defined(AHA152X_STAT)	} else {		HOSTDATA(shpnt)->busfree_without_old_command++;#endif	}	DO_LOCK(flags);	if(DONE_SC) {#if defined(AHA152X_STAT)		action++;#endif		if(SCDONE(DONE_SC)) {			Scsi_Cmnd *ptr=DONE_SC;			DONE_SC=SCDONE(DONE_SC);#if 0			if(HOSTDATA(shpnt)->debug & debug_eh) {				printk(ERR_LEAD "received sense: ", CMDINFO(ptr));				print_sense("bh", DONE_SC);			}#endif			HOSTDATA(shpnt)->commands--;			if (!HOSTDATA(shpnt)->commands)				SETPORT(PORTA, 0);	/* turn led off */			kfree(ptr->host_scribble);			kfree(ptr);		} else if(DONE_SC->SCp.Status==0x02) {#if defined(AHA152X_STAT)			HOSTDATA(shpnt)->busfree_with_check_condition++;#endif#if 0			DPRINTK(debug_eh, ERR_LEAD "CHECK CONDITION found\n", CMDINFO(DONE_SC));#endif			if(!(DONE_SC->SCp.Status & not_issued)) {				Scsi_Cmnd *cmnd = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC);				if(cmnd) {					Scsi_Cmnd *ptr=DONE_SC;					DONE_SC=0;#if 0					DPRINTK(debug_eh, ERR_LEAD "requesting sense\n", CMDINFO(ptr));#endif					cmnd->cmnd[0]         = REQUEST_SENSE;					cmnd->cmnd[1]         = 0;					cmnd->cmnd[2]         = 0;					cmnd->cmnd[3]         = 0;					cmnd->cmnd[4]         = sizeof(ptr->sense_buffer);					cmnd->cmnd[5]         = 0;					cmnd->cmd_len	      = 6;					cmnd->host            = ptr->host;					cmnd->target          = ptr->target;					cmnd->lun             = ptr->lun;					cmnd->use_sg          = 0; 					cmnd->request_buffer  = ptr->sense_buffer;					cmnd->request_bufflen = sizeof(ptr->sense_buffer);								DO_UNLOCK(flags);					aha152x_internal_queue(cmnd, 0, 0, ptr, internal_done);					DO_LOCK(flags);				} else {					printk(ERR_LEAD "allocation failed\n", CMDINFO(CURRENT_SC));					if(cmnd)						kfree(cmnd);				}			} else {#if 0				DPRINTK(debug_eh, ERR_LEAD "command not issued - CHECK CONDITION ignored\n", CMDINFO(DONE_SC));#endif							}		}		if(DONE_SC && DONE_SC->scsi_done) {			/* turn led off, when no commands are in the driver */			HOSTDATA(shpnt)->commands--;			if (!HOSTDATA(shpnt)->commands)				SETPORT(PORTA, 0);	/* turn led off */			kfree(DONE_SC->host_scribble);			DONE_SC->host_scribble=0;			DO_UNLOCK(flags);			DPRINTK(debug_done, DEBUG_LEAD "calling scsi_done(%p)\n", CMDINFO(DONE_SC), DONE_SC);                	DONE_SC->scsi_done(DONE_SC);			DPRINTK(debug_done, DEBUG_LEAD "scsi_done(%p) returned\n", CMDINFO(DONE_SC), DONE_SC);			DO_LOCK(flags);		}		DONE_SC=0;

⌨️ 快捷键说明

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