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

📄 fdc-io.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	 */	out[0] = operation;	out[1] = FTAPE_UNIT;	out[2] = buff->cyl;	out[3] = buff->head;	out[4] = buff->sect + buff->sector_offset;	out[5] = 3;		/* Sector size of 1K. */	out[6] = out[4] + buff->sector_count - 1;	/* last sector */	out[7] = 109;		/* Gap length. */	out[8] = 0xff;		/* No limit to transfer size. */	restore_flags(flags);	TRACEx4(6, "C: 0x%02x, H: 0x%02x, R: 0x%02x, cnt: 0x%02x",		out[2], out[3], out[4], out[6] - out[4] + 1);	result = fdc_command(out, 9);	if (result != 0) {		fdc_mode = fdc_idle;		TRACE(1, "fdc_command failed");	}	fdc_setup_error = result;	TRACE_EXIT;	return result;}int fdc_fifo_enable(void){	TRACE_FUN(8, "fdc_fifo_enable");	int result = 0;	byte cmd0[] = {FDC_DUMPREGS};	byte cmd1[] = {FDC_CONFIGURE, 0, 0x07, 0}; /* enable fifo, thr = 8 */	byte cmd2[] = {FDC_LOCK};	byte cmd3[] = {FDC_UNLOCK};	byte stat;	byte reg[10];	int i;	if (CLK_48MHZ && fdc.type >= i82078)		cmd1[0] |= FDC_CLK48_BIT;	if (!fdc_fifo_locked) {		/*  Dump fdc internal registers for examination		 */		result = fdc_command(cmd0, NR_ITEMS(cmd0));		if (result < 0) {			TRACE(2, "FDC dumpreg command failed, fifo unchanged");			result = -EIO;		} else {			/*  Now read fdc internal registers from fifo			 */			for (i = 0; i < NR_ITEMS(reg); ++i) {				fdc_read(&reg[i]);				TRACEx2(6, "Register %d = 0x%02x", i, reg[i]);			}			fdc_fifo_state = (reg[8] & 0x20) == 0;			fdc_lock_state = reg[7] & 0x80;			fdc_fifo_thr = 1 + (reg[8] & 0x0f);			TRACEx3(5, "original fifo state: %sabled, threshold %d, %slocked",				(fdc_fifo_state) ? "en" : "dis",			   fdc_fifo_thr, (fdc_lock_state) ? "" : "not ");			/*  If fdc is already locked, unlock it first !			 */			if (fdc_lock_state) {				fdc_ready_wait(100);				result = fdc_command(cmd3, NR_ITEMS(cmd3));				if (result < 0) {					TRACE(-1, "FDC unlock command failed, configuration unchanged");					result = -EIO;				}			}			/*  Enable fifo and set threshold at xx bytes to allow a			 *  reasonably large latency and reduce number of dma bursts.			 */			fdc_ready_wait(100);			result = fdc_command(cmd1, NR_ITEMS(cmd1));			if (result < 0) {				TRACE(-1, "FDC configure command failed, fifo unchanged");				result = -EIO;			} else {				/*  Now lock configuration so reset will not change it				 */				result = fdc_issue_command(cmd2, NR_ITEMS(cmd2), &stat, 1);				if (result < 0 || stat != 0x10) {					TRACEx1(-1, "FDC lock command failed, stat = 0x%02x", stat);					result = -EIO;				} else {					fdc_fifo_locked = 1;					result = 0;				}			}		}	} else {		TRACE(2, "Fifo not enabled because locked");	}	TRACE_EXIT;	return result;}/*   Determine fd controller type  */static byte fdc_save_state[2] = {0, 0};int fdc_probe(void){	TRACE_FUN(8, "fdc_probe");	byte cmd[1];	byte stat[16];		/* must be able to hold dumpregs & save results */	int result;	/*  Try to find out what kind of fd controller we have to deal with	 *  Scheme borrowed from floppy driver:	 *  first try if FDC_DUMPREGS command works	 *  (this indicates that we have a 82072 or better)	 *  then try the FDC_VERSION command (82072 doesn't support this)	 *  then try the FDC_UNLOCK command (some older 82077's don't support this)	 *  then try the FDC_PARTID command (82078's support this)	 */	cmd[0] = FDC_DUMPREGS;	result = fdc_issue_command(cmd, 1, stat, 1);	if (result == 0) {		if (stat[0] == 0x80) {			/* invalid command: must be pre 82072			 */			TRACE(2, "Type 8272A/765A compatible FDC found");			result = i8272;		} else {			fdc_result(&stat[1], 9);			fdc_save_state[0] = stat[7];			fdc_save_state[1] = stat[8];			cmd[0] = FDC_VERSION;			result = fdc_issue_command(cmd, 1, stat, 1);			if (result < 0 || stat[0] == 0x80) {				TRACE(2, "Type 82072 FDC found");				result = i8272;			} else if (*stat == 0x90) {				cmd[0] = FDC_UNLOCK;				result = fdc_issue_command(cmd, 1, stat, 1);				if (result < 0 || stat[0] != 0x00) {					TRACE(2, "Type pre-1991 82077 FDC found, treating it like a 82072");					result = i8272;				} else {					int i;					if (fdc_save_state[0] & 0x80) { /* was locked */						cmd[0] = FDC_LOCK; /* restore lock */						result = fdc_issue_command(cmd, 1, stat, 1);						TRACE(2, "FDC is already locked");					}					/* Test for a i82078 FDC */					cmd[0] = FDC_PARTID;					result = fdc_issue_command(cmd, 1, stat, 1);					if (result < 0 || stat[0] == 0x80) {						/* invalid command: not a i82078xx type FDC */						result = no_fdc;						for (i = 0; i < 4; ++i) {							outb_p(i, fdc.tdr);							if ((inb_p(fdc.tdr) & 0x03) != i) {								result = i82077;								break;							}						}						if (result == no_fdc) {							result = i82077AA;							TRACE(2, "Type 82077AA FDC found");						} else {							TRACE(2, "Type 82077 FDC found");						}					} else {						/* FDC_PARTID cmd succeeded */						switch (stat[0] >> 5) {						case 0x0:							/* i82078SL or i82078-1.  The SL part cannot run at 2Mbps (the							 * SL and -1 dies are identical; they are speed graded after							 * production, according to Intel).  Some SL's can be detected							 * by doing a SAVE cmd and look at bit 7 of the first byte (the							 * SEL3V# bit).  If it is 0, the part runs off 3Volts, and hence							 * it is a SL.							 */							cmd[0] = FDC_SAVE;							result = fdc_issue_command(cmd, 1, stat, 16);							if (result < 0) {								TRACE(1, "FDC_SAVE failed. Dunno why");								/* guess we better claim the fdc to be a i82078 */								result = i82078;								TRACE(2, "Type i82078 FDC (i suppose) found");							} else {								if ((stat[0] & FDC_SEL3V_BIT)) {									/* fdc running off 5Volts; Pray that it's a i82078-1									 */									TRACE(2, "Type i82078-1 or 5Volt i82078SL FDC found");									TRACE(2, "Treating it as an i82078-1 (2Mbps) FDC");									result = i82078_1;								} else {									TRACE(2, "Type 3Volt i82078SL FDC (1Mbps) found");									result = i82078;								}							}							break;						case 0x1:						case 0x2: /* S82078B (?!) */							/* 44pin i82078 found */							result = i82078;							TRACE(2, "Type i82078 FDC found");							break;						case 0x3: /* NSC PC8744 core; used in several super-IO chips */							result = i82077AA;							TRACE(2, "Type 82077AA compatible FDC found");							break;						default:							TRACE(2, "A previously undetected FDC found");							TRACEi(2, "Treating it as a 82077AA. Please report partid=",							       stat[0]);							result = i82077AA;						} /* switch(stat[ 0] >> 5) */					} /* if (result < 0 || stat[ 0] == 0x80) */				}			} else {				TRACE(2, "Unknown FDC found");				result = i8272;			}		}	} else {		TRACE(-1, "No FDC found");		result = no_fdc;	}	TRACE_EXIT;	return result;}void fdc_config_regs(unsigned fdc_base, unsigned fdc_irq, unsigned fdc_dma){	fdc.irq = fdc_irq;	fdc.dma = fdc_dma;	fdc.sra = fdc_base;	fdc.srb = fdc_base + 1;	fdc.dor = fdc_base + 2;	fdc.tdr = fdc_base + 3;	fdc.msr = fdc.dsr = fdc_base + 4;	fdc.fifo = fdc_base + 5;#if defined MACH2 || defined PROBE_FC10	fdc.dor2 = fdc_base + 6;#endif	fdc.dir = fdc.ccr = fdc_base + 7;}/*  If probing for a FC-10/20 controller the fdc base address, interrupt *  and dma channel must be specified. *  If using an alternate fdc controller, base address, interrupt and *  dma channel must be specified. */#if defined PROBE_FC10 && !defined FDC_BASE#error No FDC base address (FDC_BASE) specified in Makefile!#endif#if defined FDC_BASE && !defined FDC_IRQ#error No interrupt (FDC_IRQ) specified in Makefile!#endif#if defined FDC_BASE && !defined FDC_DMA#error No dma channel (FDC_DMA) specified in Makefile!#endifvoid fdc_config(void){	TRACE_FUN(8, "fdc_config");	static int already_done = 0;	if (!already_done) {#ifdef PROBE_FC10		int fc_type;		fdc_config_regs(FDC_BASE, FDC_IRQ, FDC_DMA);		fc_type = fc10_enable();		if (fc_type != 0) {			TRACEx1(2, "FC-%c0 controller found", '0' + fc_type);			fdc.type = fc10;			fdc.hook = &do_ftape;		} else {			TRACE(2, "FC-10/20 controller not found");			fdc.type = no_fdc;			fdc.dor2 = 0;	/* not used with std fdc */			fdc_config_regs(0x3f0, 6, 2);	/* back to std fdc again */			fdc.hook = &do_ftape;		}#else#ifdef FDC_BASE		TRACE(2, "Using fdc controller at alternate address");		fdc_config_regs(FDC_BASE, FDC_IRQ, FDC_DMA);		fdc.hook = &do_ftape;#else		TRACE(2, "Using the standard fdc controller");		fdc_config_regs(0x3f0, 6, 2);	/* std fdc */		fdc.hook = &do_ftape;#endif /* !FDC_BASE */#endif /* !PROBE_FC10 */	}	*(fdc.hook) = fdc_isr;	/* hook our handler in */	already_done = 1;	TRACE_EXIT;}static void ftape_interrupt(int irq, void *dev_id, struct pt_regs *regs){	TRACE_FUN(8, "ftape_interrupt");	void (*handler) (void) = *fdc.hook;	*fdc.hook = NULL;	if (handler) {		handler();	} else {		TRACE(-1, "Unexpected ftape interrupt");	}	TRACE_EXIT;}int fdc_grab_irq_and_dma(void){	TRACE_FUN(8, "fdc_grab_irq_and_dma");	int result = 0;	if (fdc.hook == &do_ftape) {		/*  Get fast interrupt handler.		 */		result = request_irq(fdc.irq, ftape_interrupt, SA_INTERRUPT,				     "ftape", ftape_id);		if (result) {			TRACEx1(-1, "Unable to grab IRQ%d for ftape driver", fdc.irq);			result = -EIO;		} else {			result = request_dma(fdc.dma, ftape_id);			if (result) {				TRACEx1(-1, "Unable to grab DMA%d for ftape driver", fdc.dma);				free_irq(fdc.irq, ftape_id);				result = -EIO;			} else {				enable_irq(fdc.irq);			}		}	}#ifdef FDC_DMA	if (result == 0 && FDC_DMA == 2) {		/*  Using same dma channel as standard fdc, need to disable the		 *  dma-gate on the std fdc. This couldn't be done in the floppy		 *  driver as some laptops are using the dma-gate to enter a		 *  low power or even suspended state :-(		 */		outb_p(FDC_RESET_NOT, 0x3f2);		TRACE(2, "DMA-gate on standard fdc disabled");	}#endif	TRACE_EXIT;	return result;}int fdc_release_irq_and_dma(void){	TRACE_FUN(8, "fdc_grab_irq_and_dma");	int result = 0;	if (fdc.hook == &do_ftape) {		disable_dma(fdc.dma);	/* just in case... */		free_dma(fdc.dma);		disable_irq(fdc.irq);		free_irq(fdc.irq, ftape_id);	}#ifdef FDC_DMA	if (result == 0 && FDC_DMA == 2) {		/*  Using same dma channel as standard fdc, need to disable the		 *  dma-gate on the std fdc. This couldn't be done in the floppy		 *  driver as some laptops are using the dma-gate to enter a		 *  low power or even suspended state :-(		 */		outb_p(FDC_RESET_NOT | FDC_DMA_MODE, 0x3f2);		TRACE(2, "DMA-gate on standard fdc enabled again");	}#endif	TRACE_EXIT;	return result;}int fdc_uninit(void){	TRACE_FUN(8, "fdc_uninit");	int result = 0;	if (fdc.sra != 0) {		if (fdc.dor2 == 0) {			release_region(fdc.sra, 6);			release_region(fdc.sra + 7, 1);		} else {			release_region(fdc.sra, 8);		}	}	TRACE_EXIT;	return result;}int fdc_init(void){	TRACE_FUN(8, "fdc_init");	int result = 0;	fdc_config();	if (fdc_grab_irq_and_dma() < 0) {		result = -EBUSY;	} else {		ftape_motor = 0;		fdc_catch_stray_interrupts(1);	/* one always comes */		TRACE(5, "resetting fdc");		fdc_reset();	/* init fdc & clear track counters */		if (fdc.type == no_fdc) {	/* default, means no FC-10 or 20 found */			fdc.type = fdc_probe();		}		if (fdc.type != no_fdc) {			if (fdc.type >= i82077) {				if (fdc_fifo_enable() < 0) {					TRACE(2, "couldn't enable fdc fifo !");				} else {					TRACE(5, "fdc fifo enabled and locked");				}			}		} else {			fdc_release_irq_and_dma();			result = -EIO;		}	}	if (result >= 0) {		if (fdc.dor2 == 0) {			request_region(fdc.sra, 6, "fdc (ftape)");			request_region(fdc.sra + 7, 1, "fdc (ftape)");		} else {			request_region(fdc.sra, 8, "fdc (ftape)");		}	}	TRACE_EXIT;	return result;}

⌨️ 快捷键说明

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