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

📄 cmd_fdc.c

📁 F:worksip2440a board可启动u-boot-like.tar.gz F:worksip2440a board可启动u-boot-like.tar.gz
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * (C) Copyright 2001 * Denis Peter, MPL AG, d.peter@mpl.ch. * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * *//* * Floppy Disk support */#include <common.h>#include <config.h>#include <command.h>#include <image.h>#undef	FDC_DEBUG#ifdef	FDC_DEBUG#define	PRINTF(fmt,args...)	printf (fmt ,##args)#else#define PRINTF(fmt,args...)#endif#ifndef	TRUE#define TRUE            1#endif#ifndef FALSE#define FALSE           0#endif/*#if (CONFIG_COMMANDS & CFG_CMD_DATE) *//*#include <rtc.h> *//*#endif */#if ((CONFIG_COMMANDS & CFG_CMD_FDC) || (CONFIG_COMMANDS & CFG_CMD_FDOS))typedef struct {	int						flags;		/* connected drives ect */	unsigned long blnr;			/* Logical block nr */	uchar					drive; 		/* drive no */	uchar					cmdlen; 	/* cmd length */	uchar					cmd[16]; 	/* cmd desc */	uchar					dma;			/* if > 0 dma enabled */	uchar					result[11];/* status information */	uchar					resultlen; /* lenght of result */} FDC_COMMAND_STRUCT;/* flags: only the lower 8bit used: * bit 0 if set drive 0 is present * bit 1 if set drive 1 is present * bit 2 if set drive 2 is present * bit 3 if set drive 3 is present * bit 4 if set disk in drive 0 is inserted * bit 5 if set disk in drive 1 is inserted * bit 6 if set disk in drive 2 is inserted * bit 7 if set disk in drive 4 is inserted *//* cmd indexes */#define COMMAND 		0#define DRIVE 			1#define CONFIG0			1#define SPEC_HUTSRT	1#define TRACK 			2#define CONFIG1			2#define SPEC_HLT		2#define HEAD				3#define CONFIG2			3#define SECTOR 			4#define SECTOR_SIZE	5#define LAST_TRACK	6#define GAP					7#define DTL					8/* result indexes */#define STATUS_0						0#define STATUS_PCN					1#define STATUS_1						1#define STATUS_2						2#define STATUS_TRACK				3#define STATUS_HEAD					4#define STATUS_SECT					5#define STATUS_SECT_SIZE		6/* Register addresses */#define FDC_BASE	0x3F0#define FDC_SRA		FDC_BASE + 0	/* Status Register A */#define FDC_SRB		FDC_BASE + 1	/* Status Register B */#define FDC_DOR		FDC_BASE + 2	/* Digital Output Register */#define FDC_TDR		FDC_BASE + 3	/* Tape Drive Register */#define FDC_DSR		FDC_BASE + 4	/* Data rate Register */#define FDC_MSR		FDC_BASE + 4	/* Main Status Register */#define FDC_FIFO	FDC_BASE + 5	/* FIFO */#define FDC_DIR		FDC_BASE + 6	/* Digital Input Register */#define FDC_CCR		FDC_BASE + 7	/* Configuration Control *//* Commands */#define FDC_CMD_SENSE_INT 		0x08#define FDC_CMD_CONFIGURE 		0x13#define FDC_CMD_SPECIFY	 			0x03#define FDC_CMD_RECALIBRATE 	0x07#define FDC_CMD_READ				 	0x06#define FDC_CMD_READ_TRACK	 	0x02#define FDC_CMD_READ_ID			 	0x0A#define FDC_CMD_DUMP_REG		 	0x0E#define FDC_CMD_SEEK				 	0x0F#define FDC_CMD_SENSE_INT_LEN 		0x01#define FDC_CMD_CONFIGURE_LEN 		0x04#define FDC_CMD_SPECIFY_LEN	 			0x03#define FDC_CMD_RECALIBRATE_LEN 	0x02#define FDC_CMD_READ_LEN				 	0x09#define FDC_CMD_READ_TRACK_LEN	 	0x09#define FDC_CMD_READ_ID_LEN			 	0x02#define FDC_CMD_DUMP_REG_LEN		 	0x01#define FDC_CMD_SEEK_LEN				 	0x03#define FDC_FIFO_THR			0x0C#define FDC_FIFO_DIS			0x00#define FDC_IMPLIED_SEEK	0x01#define FDC_POLL_DIS			0x00#define FDC_PRE_TRK				0x00#define FDC_CONFIGURE			FDC_FIFO_THR | (FDC_POLL_DIS<<4) | (FDC_FIFO_DIS<<5) | (FDC_IMPLIED_SEEK << 6)#define FDC_MFM_MODE			0x01 /* MFM enable */#define FDC_SKIP_MODE			0x00 /* skip enable */#define FDC_TIME_OUT 100000 /* time out */#define	FDC_RW_RETRIES		3 /* read write retries */#define FDC_CAL_RETRIES		3 /* calibration and seek retries *//* Disk structure */typedef struct  {	unsigned int size;			/* nr of sectors total */	unsigned int sect;			/* sectors per track */	unsigned int head;			/* nr of heads */	unsigned int track;			/* nr of tracks */	unsigned int stretch;		/* !=0 means double track steps */	unsigned char	gap;			/* gap1 size */	unsigned char	rate;			/* data rate. |= 0x40 for perpendicular */	unsigned char	spec1;		/* stepping rate, head unload time */	unsigned char	fmt_gap;	/* gap2 size */	unsigned char hlt;			/* head load time */	unsigned char sect_code; /* Sector Size code */	const char	* name; 		/* used only for predefined formats */} FD_GEO_STRUCT;/* supported Floppy types (currently only one) */const static FD_GEO_STRUCT floppy_type[2] = {	{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,16,2,"H1440" },	/*  7 1.44MB 3.5"   */	{    0, 0,0, 0,0,0x00,0x00,0x00,0x00, 0,0,NULL    },	/*  end of table    */};static FDC_COMMAND_STRUCT cmd; /* global command struct *//* If the boot drive number is undefined, we assume it's drive 0             */#ifndef CFG_FDC_DRIVE_NUMBER#define CFG_FDC_DRIVE_NUMBER 0#endif/* Hardware access */#ifndef CFG_ISA_IO_STRIDE#define CFG_ISA_IO_STRIDE 1#endif#ifndef CFG_ISA_IO_OFFSET#define CFG_ISA_IO_OFFSET 0#endif#ifdef CONFIG_AMIGAONEG3SEunsigned char INT6_Status;void fdc_interrupt(void){    INT6_Status = 0x80;}/* waits for an interrupt (polling) */int wait_for_fdc_int(void){	unsigned long timeout;	timeout = FDC_TIME_OUT;	while(((volatile)INT6_Status & 0x80) == 0) {		timeout--;		udelay(10);		if(timeout == 0) /* timeout occured */			return FALSE;	}	INT6_Status = 0;	return TRUE;}#endif/* Supporting Functions *//* reads a Register of the FDC */unsigned char read_fdc_reg(unsigned int addr){	volatile unsigned char *val =		(volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS +					   (addr * CFG_ISA_IO_STRIDE) +					   CFG_ISA_IO_OFFSET);	return val [0];}/* writes a Register of the FDC */void write_fdc_reg(unsigned int addr, unsigned char val){	volatile unsigned char *tmp =		(volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS +					   (addr * CFG_ISA_IO_STRIDE) +					   CFG_ISA_IO_OFFSET);	tmp[0]=val;}#ifndef CONFIG_AMIGAONEG3SE/* waits for an interrupt (polling) */int wait_for_fdc_int(void){	unsigned long timeout;	timeout = FDC_TIME_OUT;	while((read_fdc_reg(FDC_SRA)&0x80)==0) {		timeout--;		udelay(10);		if(timeout==0) /* timeout occured */			return FALSE;	}	return TRUE;}#endif/* reads a byte from the FIFO of the FDC and checks direction and RQM bit   of the MSR. returns -1 if timeout, or byte if ok */int read_fdc_byte(void){	unsigned long timeout;	timeout = FDC_TIME_OUT;	while((read_fdc_reg(FDC_MSR)&0xC0)!=0xC0) {		/* direction out and ready */		udelay(10);		timeout--;		if(timeout==0) /* timeout occured */			return -1;	}	return read_fdc_reg(FDC_FIFO);}/* if the direction of the FIFO is wrong, this routine is used to   empty the FIFO. Should _not_ be used */int fdc_need_more_output(void){	unsigned char c;	while((read_fdc_reg(FDC_MSR)&0xC0)==0xC0)	{			c=(unsigned char)read_fdc_byte();			printf("Error: more output: %x\n",c);	}	return TRUE;}/* writes a byte to the FIFO of the FDC and checks direction and RQM bit   of the MSR */int write_fdc_byte(unsigned char val){	unsigned long timeout;	timeout = FDC_TIME_OUT;	while((read_fdc_reg(FDC_MSR)&0xC0)!=0x80) {		/* direction in and ready for byte */		timeout--;		udelay(10);		fdc_need_more_output();		if(timeout==0) /* timeout occured */			return FALSE;	}	write_fdc_reg(FDC_FIFO,val);	return TRUE;}/* sets up all FDC commands and issues it to the FDC. If   the command causes direct results (no Execution Phase)   the result is be read as well. */int fdc_issue_cmd(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG){	int i;	unsigned long head,track,sect,timeout;	track = pCMD->blnr / (pFG->sect * pFG->head); /* track nr */	sect =  pCMD->blnr % (pFG->sect * pFG->head); /* remaining blocks */	head = sect / pFG->sect; /* head nr */	sect =  sect % pFG->sect; /* remaining blocks */	sect++; /* sectors are 1 based */	PRINTF("Cmd 0x%02x Track %ld, Head %ld, Sector %ld, Drive %d (blnr %ld)\n",		pCMD->cmd[0],track,head,sect,pCMD->drive,pCMD->blnr);	if(head|=0) { /* max heads = 2 */		pCMD->cmd[DRIVE]=pCMD->drive | 0x04; /* head 1 */		pCMD->cmd[HEAD]=(unsigned char) head; /* head register */	}	else {		pCMD->cmd[DRIVE]=pCMD->drive; /* head 0 */		pCMD->cmd[HEAD]=(unsigned char) head; /* head register */	}	pCMD->cmd[TRACK]=(unsigned char) track; /* track */	switch (pCMD->cmd[COMMAND]) {		case FDC_CMD_READ:			pCMD->cmd[SECTOR]=(unsigned char) sect; /* sector */			pCMD->cmd[SECTOR_SIZE]=pFG->sect_code; /* sector size code */			pCMD->cmd[LAST_TRACK]=pFG->sect; /* End of track */			pCMD->cmd[GAP]=pFG->gap; /* gap */			pCMD->cmd[DTL]=0xFF; /* DTL */			pCMD->cmdlen=FDC_CMD_READ_LEN;			pCMD->cmd[COMMAND]|=(FDC_MFM_MODE<<6); /* set MFM bit */			pCMD->cmd[COMMAND]|=(FDC_SKIP_MODE<<5); /* set Skip bit */			pCMD->resultlen=0;  /* result only after execution */			break;		case FDC_CMD_SEEK:			pCMD->cmdlen=FDC_CMD_SEEK_LEN;			pCMD->resultlen=0;  /* no result */			break;		case FDC_CMD_CONFIGURE:			pCMD->cmd[CONFIG0]=0;			pCMD->cmd[CONFIG1]=FDC_CONFIGURE; /* FIFO Threshold, Poll, Enable FIFO */			pCMD->cmd[CONFIG2]=FDC_PRE_TRK; 	/* Precompensation Track */			pCMD->cmdlen=FDC_CMD_CONFIGURE_LEN;			pCMD->resultlen=0;  /* no result */			break;		case FDC_CMD_SPECIFY:			pCMD->cmd[SPEC_HUTSRT]=pFG->spec1;			pCMD->cmd[SPEC_HLT]=(pFG->hlt)<<1; /* head load time */			if(pCMD->dma==0)				pCMD->cmd[SPEC_HLT]|=0x1; /* no dma */			pCMD->cmdlen=FDC_CMD_SPECIFY_LEN;			pCMD->resultlen=0;  /* no result */			break;		case FDC_CMD_DUMP_REG:			pCMD->cmdlen=FDC_CMD_DUMP_REG_LEN;			pCMD->resultlen=10;  /* 10 byte result */			break;		case FDC_CMD_READ_ID:			pCMD->cmd[COMMAND]|=(FDC_MFM_MODE<<6); /* set MFM bit */			pCMD->cmdlen=FDC_CMD_READ_ID_LEN;			pCMD->resultlen=7;  /* 7 byte result */			break;		case FDC_CMD_RECALIBRATE:			pCMD->cmd[DRIVE]&=0x03; /* don't set the head bit */			pCMD->cmdlen=FDC_CMD_RECALIBRATE_LEN;			pCMD->resultlen=0;  /* no result */			break;			break;		case FDC_CMD_SENSE_INT:			pCMD->cmdlen=FDC_CMD_SENSE_INT_LEN;			pCMD->resultlen=2;			break;	}	for(i=0;i<pCMD->cmdlen;i++) {		/* PRINTF("write cmd%d = 0x%02X\n",i,pCMD->cmd[i]); */		if(write_fdc_byte(pCMD->cmd[i])==FALSE) {			PRINTF("Error: timeout while issue cmd%d\n",i);			return FALSE;		}	}	timeout=FDC_TIME_OUT;	for(i=0;i<pCMD->resultlen;i++) {		while((read_fdc_reg(FDC_MSR)&0xC0)!=0xC0) {			timeout--;			if(timeout==0) {				PRINTF(" timeout while reading result%d MSR=0x%02X\n",i,read_fdc_reg(FDC_MSR));				return FALSE;			}		}		pCMD->result[i]=(unsigned char)read_fdc_byte();	}	return TRUE;}/* selects the drive assigned in the cmd structur and   switches on the Motor */void select_fdc_drive(FDC_COMMAND_STRUCT *pCMD){	unsigned char val;	val=(1<<(4+pCMD->drive))|pCMD->drive|0xC; /* set reset, dma gate and motor bits */	if((read_fdc_reg(FDC_DOR)&val)!=val) {		write_fdc_reg(FDC_DOR,val);		for(val=0;val<255;val++)			udelay(500); /* wait some time to start motor */	}}/* switches off the Motor of the specified drive */void stop_fdc_drive(FDC_COMMAND_STRUCT *pCMD){	unsigned char val;	val=(1<<(4+pCMD->drive))|pCMD->drive; /* sets motor bits */	write_fdc_reg(FDC_DOR,(read_fdc_reg(FDC_DOR)&~val));}/* issues a recalibrate command, waits for interrupt and * issues a sense_interrupt */int fdc_recalibrate(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG){	pCMD->cmd[COMMAND]=FDC_CMD_RECALIBRATE;	if(fdc_issue_cmd(pCMD,pFG)==FALSE)		return FALSE;	while(wait_for_fdc_int()!=TRUE);	pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;	return(fdc_issue_cmd(pCMD,pFG));}/* issues a recalibrate command, waits for interrupt and * issues a sense_interrupt */int fdc_seek(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG){	pCMD->cmd[COMMAND]=FDC_CMD_SEEK;	if(fdc_issue_cmd(pCMD,pFG)==FALSE)		return FALSE;	while(wait_for_fdc_int()!=TRUE);	pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;	return(fdc_issue_cmd(pCMD,pFG));}#ifndef CONFIG_AMIGAONEG3SE/* terminates current command, by not servicing the FIFO * waits for interrupt and fills in the result bytes */int fdc_terminate(FDC_COMMAND_STRUCT *pCMD){

⌨️ 快捷键说明

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