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

📄 cmd_ide.c

📁 嵌入式ARM的一些源代码
💻 C
📖 第 1 页 / 共 2 页
字号:


	/* Reset the IDE just to be sure.
	 * Light LED's to show
	 */
	ide_led ((LED_IDE1 | LED_IDE2), 1);		/* LED's on	*/
	ide_reset ();

#ifdef CONFIG_IDE_PCMCIA
	/* PCMCIA / IDE initialization for common mem space */
	pcmp->pcmc_pgcrb = 0;
#endif

	/* start in PIO mode 0 - most relaxed timings */
	pio_mode = 0;
	set_pcmcia_timing (pio_mode);

	/*
	 * Wait for IDE to get ready.
	 * According to spec, this can take up to 31 seconds!
	 */
	for (bus=0; bus<CFG_IDE_MAXBUS; ++bus) {
		int dev = bus * (CFG_IDE_MAXDEVICE / CFG_IDE_MAXBUS);

		printf ("Bus %d: ", bus);

		ide_bus_ok[bus] = 0;

		/* Select device
		 */
		udelay (100000);		/* 100 ms */
		outb (dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
		udelay (100000);		/* 100 ms */

		i = 0;
		do {
			udelay (10000);		/* 10 ms */

			c = inb (dev, ATA_STATUS);
			++i;
			if (i > (ATA_RESET_TIME * 100)) {
				puts ("** Timeout **\n");
				ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */
				return;
			}
			if ((i >= 100) && ((i%100)==0)) {
				putc ('.');
			}
		} while (c & ATA_STAT_BUSY);

		if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) {
			printf ("Status 0x%02x ", c);
		} else if ((c & ATA_STAT_READY) == 0) {
			puts ("not available  ");
		} else {
			puts ("OK  ");
			ide_bus_ok[bus] = 1;
		}
	}
	putc ('\n');

	ide_led ((LED_IDE1 | LED_IDE2), 0);	/* LED's off	*/

	curr_device = -1;
	for (i=0; i<CFG_IDE_MAXDEVICE; ++i) {
#ifdef CONFIG_IDE_LED
		int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2;
#endif

		if (!ide_bus_ok[IDE_BUS(i)])
			continue;
		ide_led (led, 1);		/* LED on	*/
		ide_ident (i);
		ide_led (led, 0);		/* LED off	*/
		ide_print (i);

		/* make first available device current */
		if ((ide_device[i].size > 0) && (curr_device < 0)) {
			curr_device = i;
		}
	}
}

/* ------------------------------------------------------------------------- */

#ifdef CONFIG_IDE_PCMCIA

static void
set_pcmcia_timing (int pmode)
{
	volatile immap_t *immr = (immap_t *)CFG_IMMR;
	volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia);
	ulong timings;

	timings = PCMCIA_SHT(pio_config_clk[pmode].t_hold)
		| PCMCIA_SST(pio_config_clk[pmode].t_setup)
		| PCMCIA_SL (pio_config_clk[pmode].t_length)
		;

	/* IDE 0
	 */
	pcmp->pcmc_pbr0 = CFG_PCMCIA_PBR0;
	pcmp->pcmc_por0 = CFG_PCMCIA_POR0
#if (CFG_PCMCIA_POR0 != 0)
			| timings
#endif
			;

	pcmp->pcmc_pbr1 = CFG_PCMCIA_PBR1;
	pcmp->pcmc_por1 = CFG_PCMCIA_POR1
#if (CFG_PCMCIA_POR1 != 0)
			| timings
#endif
			;

	pcmp->pcmc_pbr2 = CFG_PCMCIA_PBR2;
	pcmp->pcmc_por2 = CFG_PCMCIA_POR2
#if (CFG_PCMCIA_POR2 != 0)
			| timings
#endif
			;

	pcmp->pcmc_pbr3 = CFG_PCMCIA_PBR3;
	pcmp->pcmc_por3 = CFG_PCMCIA_POR3
#if (CFG_PCMCIA_POR3 != 0)
			| timings
#endif
			;

	/* IDE 1
	 */
	pcmp->pcmc_pbr4 = CFG_PCMCIA_PBR4;
	pcmp->pcmc_por4 = CFG_PCMCIA_POR4
#if (CFG_PCMCIA_POR4 != 0)
			| timings
#endif
			;

	pcmp->pcmc_pbr5 = CFG_PCMCIA_PBR5;
	pcmp->pcmc_por5 = CFG_PCMCIA_POR5
#if (CFG_PCMCIA_POR5 != 0)
			| timings
#endif
			;

	pcmp->pcmc_pbr6 = CFG_PCMCIA_PBR6;
	pcmp->pcmc_por6 = CFG_PCMCIA_POR6
#if (CFG_PCMCIA_POR6 != 0)
			| timings
#endif
			;

	pcmp->pcmc_pbr7 = CFG_PCMCIA_PBR7;
	pcmp->pcmc_por7 = CFG_PCMCIA_POR7
#if (CFG_PCMCIA_POR7 != 0)
			| timings
#endif
			;

}

#endif	/* CONFIG_IDE_PCMCIA */

/* ------------------------------------------------------------------------- */

static void __inline__
outb(int dev, int port, unsigned char val)
{
	/* Ensure I/O operations complete */
	__asm__ volatile("eieio");
	*((uchar *)(ATA_CURR_BASE(dev)+port)) = val;
#if 0
printf ("OUTB: 0x%08lx <== 0x%02x\n", ATA_CURR_BASE(dev)+port, val);
#endif
}

static unsigned char __inline__
inb(int dev, int port)
{
	uchar val;
	/* Ensure I/O operations complete */
	__asm__ volatile("eieio");
	val = *((uchar *)(ATA_CURR_BASE(dev)+port));
#if 0
printf ("INB: 0x%08lx ==> 0x%02x\n", ATA_CURR_BASE(dev)+port, val);
#endif
	return (val);
}

static void
input_swap_data(int dev, ulong *sect_buf, int words)
{
	volatile ushort	*pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);
	ushort	*dbuf = (ushort *)sect_buf;

	while (words--) {
		*dbuf++ = ld_le16(pbuf);
		*dbuf++ = ld_le16(pbuf);
	}
}

static void
output_data(int dev, ulong *sect_buf, int words)
{
	ushort	*dbuf;
	volatile ushort	*pbuf;

	pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);
	dbuf = (ushort *)sect_buf;
	while (words--) {
		__asm__ volatile ("eieio");
		*pbuf = *dbuf++;
		__asm__ volatile ("eieio");
		*pbuf = *dbuf++;
	}
}

static void
input_data(int dev, ulong *sect_buf, int words)
{
	ushort	*dbuf;
	volatile ushort	*pbuf;

	pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG);
	dbuf = (ushort *)sect_buf;
	while (words--) {
		__asm__ volatile ("eieio");
		*dbuf++ = *pbuf;
		__asm__ volatile ("eieio");
		*dbuf++ = *pbuf;
	}
}

/* -------------------------------------------------------------------------
 */
static void ide_ident (int device)
{
	ulong iobuf[ATA_SECTORWORDS];
	unsigned char c;
	hd_driveid_t *iop = (hd_driveid_t *)iobuf;
	ide_dev_id_t *idp = &(ide_device[device]);
#if 0
	int mode, cycle_time;
#endif

	printf ("    Device %d: ", device);

	ide_led (DEVICE_LED(device), 1);	/* LED on	*/
	/* Select device
	 */
	outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));

	/* Start Ident Command
	 */
	outb (device, ATA_COMMAND, ATA_CMD_IDENT);

	/* Wait for completion
	 */
	c = ide_wait (device, 100);

	ide_led (DEVICE_LED(device), 0);	/* LED off	*/

	if (((c & ATA_STAT_READY) == 0) ||
	    ((c & (ATA_STAT_FAULT|ATA_STAT_ERR)) != 0) ) {
		idp->size = 0;
		idp->model[0] = idp->serial_no[0] = '\0';
		return;
	}

	input_swap_data (device, iobuf, ATA_SECTORWORDS);

	trim_trail (iop->model,     sizeof(iop->model));
	trim_trail (iop->serial_no, sizeof(iop->serial_no));

#if 0
	/*
	 * Drive PIO mode autoselection
	 */
	mode = iop->tPIO;

	printf ("tPIO = 0x%02x = %d\n",mode, mode);
	if (mode > 2) {		/* 2 is maximum allowed tPIO value */
		mode = 2;
		PRINTF ("Override tPIO -> 2\n");
	}
	if (iop->field_valid & 2) {	/* drive implements ATA2? */
		PRINTF ("Drive implements ATA2\n");
		if (iop->capability & 8) {	/* drive supports use_iordy? */
			cycle_time = iop->eide_pio_iordy; 
		} else {
			cycle_time = iop->eide_pio;
		}
		PRINTF ("cycle time = %d\n", cycle_time);
		mode = 4;
		if (cycle_time > 120) mode = 3;	/* 120 ns for PIO mode 4 */
		if (cycle_time > 180) mode = 2;	/* 180 ns for PIO mode 3 */
		if (cycle_time > 240) mode = 1;	/* 240 ns for PIO mode 4 */
		if (cycle_time > 383) mode = 0;	/* 383 ns for PIO mode 4 */
	}
printf ("PIO mode to use: PIO %d\n", mode);
#endif

	/* swap shorts */
	idp->size = (iop->lba_capacity << 16) | (iop->lba_capacity >> 16);

	strncpy (idp->model,     iop->model,     sizeof(idp->model));
	strncpy (idp->serial_no, iop->serial_no, sizeof(idp->serial_no));
}

/* ------------------------------------------------------------------------- */

static void ide_print (int device)
{
	ldiv_t mb, gb;
	ide_dev_id_t *idp = &(ide_device[device]);

	if (idp->size == 0) {
		puts ("not available\n");
		return;
	}

	mb = ldiv(idp->size, ((1024 * 1024) / 512)); /* MB */
	/* round to 1 digit */
	mb.rem *= 10 * 512;
	mb.rem += 512 * 1024;
	mb.rem /= 1024 * 1024;

	gb = ldiv(10 * mb.quot + mb.rem, 10240);
	gb.rem += 512;
	gb.rem /= 1024;

	printf ("Model: %s  Serial #: %s  ", idp->model, idp->serial_no);
	printf ("Capacity: %ld.%ld MB = %ld.%ld GB\n",
		mb.quot, mb.rem, gb.quot, gb.rem);
}

/* ------------------------------------------------------------------------- */

ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)
{
	ulong n = 0;
	unsigned char c;

	ide_led (DEVICE_LED(device), 1);	/* LED on	*/

	/* Select device
	 */
	outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));

	while (blkcnt-- > 0) {

		c = ide_wait (device, 500);

		if (c & ATA_STAT_BUSY) {
			printf ("IDE read: device %d not ready\n", device);
			goto RD_OUT;
		}

		outb (device, ATA_SECT_CNT, 1);
		outb (device, ATA_LBA_LOW,  (blknr >>  0) & 0xFF);
		outb (device, ATA_LBA_MID,  (blknr >>  8) & 0xFF);
		outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
		outb (device, ATA_DEV_HD,   ATA_LBA | ATA_DEVICE(device));
		outb (device, ATA_COMMAND,  ATA_CMD_READ);

		udelay (50);

		c = ide_wait (device, 500);	/* can't take over 500 ms */

		if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != ATA_STAT_DRQ) {
			printf ("Error (no IRQ) dev %d blk %ld: status 0x%02x\n",
				device, blknr, c);
			goto RD_OUT;
		}

		input_data (device, buffer, ATA_SECTORWORDS);
		(void) inb (device, ATA_STATUS);	/* clear IRQ */

		++n;
		++blknr;
		buffer += ATA_SECTORWORDS;
	}
RD_OUT:
	ide_led (DEVICE_LED(device), 0);	/* LED off	*/
	return (n);
}

/* ------------------------------------------------------------------------- */


ulong ide_write (int device, ulong blknr, ulong blkcnt, ulong *buffer)
{
	ulong n = 0;
	unsigned char c;

	ide_led (DEVICE_LED(device), 1);	/* LED on	*/

	/* Select device
	 */
	outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));

	while (blkcnt-- > 0) {

		c = ide_wait (device, 500);

		if (c & ATA_STAT_BUSY) {
			printf ("IDE read: device %d not ready\n", device);
			goto WR_OUT;
		}

		outb (device, ATA_SECT_CNT, 1);
		outb (device, ATA_LBA_LOW,  (blknr >>  0) & 0xFF);
		outb (device, ATA_LBA_MID,  (blknr >>  8) & 0xFF);
		outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
		outb (device, ATA_DEV_HD,   ATA_LBA | ATA_DEVICE(device));
		outb (device, ATA_COMMAND,  ATA_CMD_WRITE);

		udelay (50);

		c = ide_wait (device, 500);	/* can't take over 500 ms */

		if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != ATA_STAT_DRQ) {
			printf ("Error (no IRQ) dev %d blk %ld: status 0x%02x\n",
				device, blknr, c);
			goto WR_OUT;
		}

		output_data (device, buffer, ATA_SECTORWORDS);
		c = inb (device, ATA_STATUS);	/* clear IRQ */
		++n;
		++blknr;
		buffer += ATA_SECTORWORDS;
	}
WR_OUT:
	ide_led (DEVICE_LED(device), 0);	/* LED off	*/
	return (n);
}

/* ------------------------------------------------------------------------- */

/* Trim trailing blanks, and NUL-terminate string
 */
static void trim_trail (unsigned char *str, unsigned int len)
{
	unsigned char *p = str + len - 1;

	while (len-- > 0) {
		*p-- = '\0';
		if (*p != ' ') {
			return;
		}
	}
}

/* ------------------------------------------------------------------------- */

/*
 * Wait until Busy bit is off, or timeout (in ms)
 * Return last status
 */
static uchar ide_wait (int dev, ulong t)
{
	ulong delay = 10 * t;		/* poll every 100 us */
	uchar c;

	while ((c = inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {
		udelay (100);
		if (delay-- == 0) {
			break;
		}
	}
	return (c);
}

/* ------------------------------------------------------------------------- */

#ifdef CONFIG_IDE_RESET

static void ide_reset (void)
{
	int i;
	volatile immap_t *immr = (immap_t *)CFG_IMMR;

	curr_device = -1;
	for (i=0; i<CFG_IDE_MAXBUS; ++i)
		ide_bus_ok[i] = 0;
	for (i=0; i<CFG_IDE_MAXDEVICE; ++i)
		ide_device[i].size = 0;

#if defined(CFG_PC_IDE_RESET)
	/* Configure PC for IDE Reset Pin
	 */
	immr->im_ioport.iop_pcdat &= ~(CFG_PC_IDE_RESET);	/* Set reset bit */
	immr->im_ioport.iop_pcpar &= ~(CFG_PC_IDE_RESET);
	immr->im_ioport.iop_pcso  &= ~(CFG_PC_IDE_RESET);
	immr->im_ioport.iop_pcdir |=   CFG_PC_IDE_RESET;	/* Make output	*/

	/* assert IDE RESET signal */
	immr->im_ioport.iop_pcdat &= ~(CFG_PC_IDE_RESET);
	udelay (20000);
	/* de-assert RESET signal of IDE */
	immr->im_ioport.iop_pcdat |=   CFG_PC_IDE_RESET;
#else
#error IDE reset pin not configured
#endif
	udelay (100000);
}

#endif	/* CONFIG_IDE_RESET */

/* ------------------------------------------------------------------------- */

#ifdef CONFIG_IDE_LED

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 */

/* ------------------------------------------------------------------------- */

#endif	/* CONFIG_COMMANDS & CFG_CMD_IDE */

⌨️ 快捷键说明

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