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

📄 cmd_ide.c

📁 F:worksip2440a board可启动u-boot-like.tar.gz F:worksip2440a board可启动u-boot-like.tar.gz
💻 C
📖 第 1 页 / 共 4 页
字号:
static	uchar	led_buffer = 0;		/* Buffer for current LED status	*/static void ide_led (uchar led, uchar status){	uchar *led_port = LED_PORT;	if (status)	{		/* switch LED on	*/		led_buffer |=  led;	} else {			/* switch LED off	*/		led_buffer &= ~led;	}	*led_port = led_buffer;}#endif	/* CONFIG_IDE_LED *//* ------------------------------------------------------------------------- */#ifdef CONFIG_ATAPI/**************************************************************************** * ATAPI Support */#undef	ATAPI_DEBUG#ifdef	ATAPI_DEBUG#define	AT_PRINTF(fmt,args...)	printf (fmt ,##args)#else#define AT_PRINTF(fmt,args...)#endif#if defined(__PPC__) || defined(CONFIG_PXA_PCMCIA)/* since ATAPI may use commands with not 4 bytes alligned length * we have our own transfer functions, 2 bytes alligned */static voidoutput_data_shorts(int dev, ushort *sect_buf, int shorts){#ifndef CONFIG_HMI10	ushort	*dbuf;	volatile ushort	*pbuf;	pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);	dbuf = (ushort *)sect_buf;	PRINTF("in output data shorts base for read is %lx\n", (unsigned long) pbuf);	while (shorts--) {		EIEIO;		*pbuf = *dbuf++;	}#else	/* CONFIG_HMI10 */	uchar	*dbuf;	volatile uchar	*pbuf_even;	volatile uchar	*pbuf_odd;	pbuf_even = (uchar *)(ATA_CURR_BASE(dev)+ATA_DATA_EVEN);	pbuf_odd  = (uchar *)(ATA_CURR_BASE(dev)+ATA_DATA_ODD);	while (shorts--) {		EIEIO;		*pbuf_even = *dbuf++;		EIEIO;		*pbuf_odd = *dbuf++;	}#endif	/* CONFIG_HMI10 */}static voidinput_data_shorts(int dev, ushort *sect_buf, int shorts){#ifndef CONFIG_HMI10	ushort	*dbuf;	volatile ushort	*pbuf;	pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);	dbuf = (ushort *)sect_buf;	PRINTF("in input data shorts base for read is %lx\n", (unsigned long) pbuf);	while (shorts--) {		EIEIO;		*dbuf++ = *pbuf;	}#else	/* CONFIG_HMI10 */	uchar	*dbuf;	volatile uchar	*pbuf_even;	volatile uchar	*pbuf_odd;	pbuf_even = (uchar *)(ATA_CURR_BASE(dev)+ATA_DATA_EVEN);	pbuf_odd  = (uchar *)(ATA_CURR_BASE(dev)+ATA_DATA_ODD);	while (shorts--) {		EIEIO;		*dbuf++ = *pbuf_even;		EIEIO;		*dbuf++ = *pbuf_odd;	}#endif	/* CONFIG_HMI10 */}#else	/* ! __PPC__ */static voidoutput_data_shorts(int dev, ushort *sect_buf, int shorts){	outsw(ATA_CURR_BASE(dev)+ATA_DATA_REG, sect_buf, shorts);}static voidinput_data_shorts(int dev, ushort *sect_buf, int shorts){	insw(ATA_CURR_BASE(dev)+ATA_DATA_REG, sect_buf, shorts);}#endif	/* __PPC__ *//* * Wait until (Status & mask) == res, or timeout (in ms) * Return last status * This is used since some ATAPI CD ROMs clears their Busy Bit first * and then they set their DRQ Bit */static uchar atapi_wait_mask (int dev, ulong t,uchar mask, uchar res){	ulong delay = 10 * t;		/* poll every 100 us */	uchar c;	c = ide_inb(dev,ATA_DEV_CTL); /* prevents to read the status before valid */	while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) {		/* break if error occurs (doesn't make sense to wait more) */		if((c & ATA_STAT_ERR)==ATA_STAT_ERR)			break;		udelay (100);		if (delay-- == 0) {			break;		}	}	return (c);}/* * issue an atapi command */unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned char * buffer,int buflen){	unsigned char c,err,mask,res;	int n;	ide_led (DEVICE_LED(device), 1);	/* LED on	*/	/* Select device	 */	mask = ATA_STAT_BUSY|ATA_STAT_DRQ;	res = 0;#ifdef	CONFIG_AMIGAONEG3SE# warning THF: Removed LBA mode ???#endif	ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));	c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);	if ((c & mask) != res) {		printf ("ATAPI_ISSUE: device %d not ready status %X\n", device,c);		err=0xFF;		goto AI_OUT;	}	/* write taskfile */	ide_outb (device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */	ide_outb (device, ATA_SECT_CNT, 0);	ide_outb (device, ATA_SECT_NUM, 0);	ide_outb (device, ATA_CYL_LOW,  (unsigned char)(buflen & 0xFF));	ide_outb (device, ATA_CYL_HIGH, (unsigned char)((buflen>>8) & 0xFF));#ifdef	CONFIG_AMIGAONEG3SE# warning THF: Removed LBA mode ???#endif	ide_outb (device, ATA_DEV_HD,   ATA_LBA | ATA_DEVICE(device));	ide_outb (device, ATA_COMMAND,  ATAPI_CMD_PACKET);	udelay (50);	mask = ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR;	res = ATA_STAT_DRQ;	c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);	if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */		printf ("ATTAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n",device,c);		err=0xFF;		goto AI_OUT;	}	output_data_shorts (device, (unsigned short *)ccb,ccblen/2); /* write command block */ 	/* ATAPI Command written wait for completition */	udelay (5000); /* device must set bsy */	mask = ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR;	/* if no data wait for DRQ = 0 BSY = 0	 * if data wait for DRQ = 1 BSY = 0 */	res=0;	if(buflen)		res = ATA_STAT_DRQ;	c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);	if ((c & mask) != res ) {		if (c & ATA_STAT_ERR) {			err=(ide_inb(device,ATA_ERROR_REG))>>4;			AT_PRINTF("atapi_issue 1 returned sense key %X status %02X\n",err,c);		} else {			printf ("ATTAPI_ISSUE: (no DRQ) after sending ccb (%x)  status 0x%02x\n", ccb[0],c);			err=0xFF;		}		goto AI_OUT;	}	n=ide_inb(device, ATA_CYL_HIGH);	n<<=8;	n+=ide_inb(device, ATA_CYL_LOW);	if(n>buflen) {		printf("ERROR, transfer bytes %d requested only %d\n",n,buflen);		err=0xff;		goto AI_OUT;	}	if((n==0)&&(buflen<0)) {		printf("ERROR, transfer bytes %d requested %d\n",n,buflen);		err=0xff;		goto AI_OUT;	}	if(n!=buflen) {		AT_PRINTF("WARNING, transfer bytes %d not equal with requested %d\n",n,buflen);	}	if(n!=0) { /* data transfer */		AT_PRINTF("ATAPI_ISSUE: %d Bytes to transfer\n",n);		 /* we transfer shorts */		n>>=1;		/* ok now decide if it is an in or output */		if ((ide_inb(device, ATA_SECT_CNT)&0x02)==0) {			AT_PRINTF("Write to device\n");			output_data_shorts(device,(unsigned short *)buffer,n);		} else {			AT_PRINTF("Read from device @ %p shorts %d\n",buffer,n);			input_data_shorts(device,(unsigned short *)buffer,n);		}	}	udelay(5000); /* seems that some CD ROMs need this... */	mask = ATA_STAT_BUSY|ATA_STAT_ERR;	res=0;	c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);	if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {		err=(ide_inb(device,ATA_ERROR_REG) >> 4);		AT_PRINTF("atapi_issue 2 returned sense key %X status %X\n",err,c);	} else {		err = 0;	}AI_OUT:	ide_led (DEVICE_LED(device), 0);	/* LED off	*/	return (err);}/* * sending the command to atapi_issue. If an status other than good * returns, an request_sense will be issued */#define ATAPI_DRIVE_NOT_READY 	100#define ATAPI_UNIT_ATTN		10unsigned char atapi_issue_autoreq (int device,				   unsigned char* ccb,				   int ccblen,				   unsigned char *buffer,				   int buflen){	unsigned char sense_data[18],sense_ccb[12];	unsigned char res,key,asc,ascq;	int notready,unitattn;#ifdef CONFIG_AMIGAONEG3SE	char *s;	unsigned int timeout, retrycnt;	s = getenv("ide_cd_timeout");	timeout = s ? (simple_strtol(s, NULL, 10)*1000000)/5 : 0;	retrycnt = 0;#endif	unitattn=ATAPI_UNIT_ATTN;	notready=ATAPI_DRIVE_NOT_READY;retry:	res= atapi_issue(device,ccb,ccblen,buffer,buflen);	if (res==0)		return (0); /* Ok */	if (res==0xFF)		return (0xFF); /* error */	AT_PRINTF("(auto_req)atapi_issue returned sense key %X\n",res);	memset(sense_ccb,0,sizeof(sense_ccb));	memset(sense_data,0,sizeof(sense_data));	sense_ccb[0]=ATAPI_CMD_REQ_SENSE;	sense_ccb[4]=18; /* allocation Length */	res=atapi_issue(device,sense_ccb,12,sense_data,18);	key=(sense_data[2]&0xF);	asc=(sense_data[12]);	ascq=(sense_data[13]);	AT_PRINTF("ATAPI_CMD_REQ_SENSE returned %x\n",res);	AT_PRINTF(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n",		sense_data[0],		key,		asc,		ascq);	if((key==0))		return 0; /* ok device ready */	if((key==6)|| (asc==0x29) || (asc==0x28)) { /* Unit Attention */		if(unitattn-->0) {			udelay(200*1000);			goto retry;		}		printf("Unit Attention, tried %d\n",ATAPI_UNIT_ATTN);		goto error;	}	if((asc==0x4) && (ascq==0x1)) { /* not ready, but will be ready soon */		if (notready-->0) {			udelay(200*1000);			goto retry;		}		printf("Drive not ready, tried %d times\n",ATAPI_DRIVE_NOT_READY);		goto error;	}	if(asc==0x3a) {		AT_PRINTF("Media not present\n");		goto error;	}#ifdef CONFIG_AMIGAONEG3SE	if ((sense_data[2]&0xF)==0x0B) {		AT_PRINTF("ABORTED COMMAND...retry\n");		if (retrycnt++ < 4)			goto retry;		return (0xFF);	}	if ((sense_data[2]&0xf) == 0x02 &&	    sense_data[12] == 0x04	&&	    sense_data[13] == 0x01	) {		AT_PRINTF("Waiting for unit to become active\n");		udelay(timeout);		if (retrycnt++ < 4)			goto retry;		return 0xFF;	}#endif	/* CONFIG_AMIGAONEG3SE */	printf ("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n",key,asc,ascq);error:	AT_PRINTF ("ERROR Sense key %02X ASC %02X ASCQ %02X\n",key,asc,ascq);	return (0xFF);}static void	atapi_inquiry(block_dev_desc_t * dev_desc){	unsigned char ccb[12]; /* Command descriptor block */	unsigned char iobuf[64]; /* temp buf */	unsigned char c;	int device;	device=dev_desc->dev;	dev_desc->type=DEV_TYPE_UNKNOWN; /* not yet valid */	dev_desc->block_read=atapi_read;	memset(ccb,0,sizeof(ccb));	memset(iobuf,0,sizeof(iobuf));	ccb[0]=ATAPI_CMD_INQUIRY;	ccb[4]=40; /* allocation Legnth */	c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,40);	AT_PRINTF("ATAPI_CMD_INQUIRY returned %x\n",c);	if (c!=0)		return;	/* copy device ident strings */	ident_cpy(dev_desc->vendor,&iobuf[8],8);	ident_cpy(dev_desc->product,&iobuf[16],16);	ident_cpy(dev_desc->revision,&iobuf[32],5);	dev_desc->lun=0;	dev_desc->lba=0;	dev_desc->blksz=0;	dev_desc->type=iobuf[0] & 0x1f;	if ((iobuf[1]&0x80)==0x80)		dev_desc->removable = 1;	else		dev_desc->removable = 0;	memset(ccb,0,sizeof(ccb));	memset(iobuf,0,sizeof(iobuf));	ccb[0]=ATAPI_CMD_START_STOP;	ccb[4]=0x03; /* start */	c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,0);	AT_PRINTF("ATAPI_CMD_START_STOP returned %x\n",c);	if (c!=0)		return;	memset(ccb,0,sizeof(ccb));	memset(iobuf,0,sizeof(iobuf));	c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,0);	AT_PRINTF("ATAPI_CMD_UNIT_TEST_READY returned %x\n",c);	if (c!=0)		return;	memset(ccb,0,sizeof(ccb));	memset(iobuf,0,sizeof(iobuf));	ccb[0]=ATAPI_CMD_READ_CAP;	c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,8);	AT_PRINTF("ATAPI_CMD_READ_CAP returned %x\n",c);	if (c!=0)		return;	AT_PRINTF("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n",		iobuf[0],iobuf[1],iobuf[2],iobuf[3],		iobuf[4],iobuf[5],iobuf[6],iobuf[7]);	dev_desc->lba  =((unsigned long)iobuf[0]<<24) +			((unsigned long)iobuf[1]<<16) +			((unsigned long)iobuf[2]<< 8) +			((unsigned long)iobuf[3]);	dev_desc->blksz=((unsigned long)iobuf[4]<<24) +			((unsigned long)iobuf[5]<<16) +			((unsigned long)iobuf[6]<< 8) +			((unsigned long)iobuf[7]);#ifdef CONFIG_LBA48	dev_desc->lba48 = 0; /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */#endif	return;}/* * atapi_read: * we transfer only one block per command, since the multiple DRQ per * command is not yet implemented */#define ATAPI_READ_MAX_BYTES	2048	/* we read max 2kbytes */#define ATAPI_READ_BLOCK_SIZE	2048	/* assuming CD part */#define ATAPI_READ_MAX_BLOCK ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE	/* max blocks */ulong atapi_read (int device, lbaint_t blknr, ulong blkcnt, ulong *buffer){	ulong n = 0;	unsigned char ccb[12]; /* Command descriptor block */	ulong cnt;	AT_PRINTF("atapi_read dev %d start %lX, blocks %lX buffer at %lX\n",		device, blknr, blkcnt, (ulong)buffer);	do {		if (blkcnt>ATAPI_READ_MAX_BLOCK) {			cnt=ATAPI_READ_MAX_BLOCK;		} else {			cnt=blkcnt;		}		ccb[0]=ATAPI_CMD_READ_12;		ccb[1]=0; /* reserved */		ccb[2]=(unsigned char) (blknr>>24) & 0xFF; /* MSB Block */		ccb[3]=(unsigned char) (blknr>>16) & 0xFF; /*  */		ccb[4]=(unsigned char) (blknr>> 8) & 0xFF;		ccb[5]=(unsigned char)  blknr      & 0xFF; /* LSB Block */		ccb[6]=(unsigned char) (cnt  >>24) & 0xFF; /* MSB Block count */		ccb[7]=(unsigned char) (cnt  >>16) & 0xFF;		ccb[8]=(unsigned char) (cnt  >> 8) & 0xFF;		ccb[9]=(unsigned char)  cnt	   & 0xFF; /* LSB Block */		ccb[10]=0; /* reserved */		ccb[11]=0; /* reserved */		if (atapi_issue_autoreq(device,ccb,12,					(unsigned char *)buffer,					cnt*ATAPI_READ_BLOCK_SIZE) == 0xFF) {			return (n);		}		n+=cnt;		blkcnt-=cnt;		blknr+=cnt;		buffer+=cnt*(ATAPI_READ_BLOCK_SIZE/4); /* ulong blocksize in ulong */	} while (blkcnt > 0);	return (n);}/* ------------------------------------------------------------------------- */#endif /* CONFIG_ATAPI */U_BOOT_CMD(	ide,  5,  1,  do_ide,	"ide     - IDE sub-system\n",	"reset - reset IDE controller\n"	"ide info  - show available IDE devices\n"	"ide device [dev] - show or set current device\n"	"ide part [dev] - print partition table of one or all IDE devices\n"	"ide read  addr blk# cnt\n"	"ide write addr blk# cnt - read/write `cnt'"	" blocks starting at block `blk#'\n"	"    to/from memory address `addr'\n");U_BOOT_CMD(	diskboot,	3,	1,	do_diskboot,	"diskboot- boot from IDE device\n",	"loadAddr dev:part\n");#endif	/* CONFIG_COMMANDS & CFG_CMD_IDE */

⌨️ 快捷键说明

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