Skip to content
Snippets Groups Projects
ide.c 29.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
    	c = ide_wait(device, IDE_TIME_OUT);
    
    	if (c & ATA_STAT_BUSY) {
    		printf("IDE read: device %d not ready\n", device);
    		goto IDE_READ_E;
    	}
    
    	/* first check if the drive is in Powersaving mode, if yes,
    	 * increase the timeout value */
    	ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR);
    	udelay(50);
    
    	c = ide_wait(device, IDE_TIME_OUT);	/* can't take over 500 ms */
    
    	if (c & ATA_STAT_BUSY) {
    		printf("IDE read: device %d not ready\n", device);
    		goto IDE_READ_E;
    	}
    	if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
    		printf("No Powersaving mode %X\n", c);
    	} else {
    		c = ide_inb(device, ATA_SECT_CNT);
    		debug("Powersaving %02X\n", c);
    		if (c == 0)
    			pwrsave = 1;
    	}
    
    
    	while (blkcnt-- > 0) {
    		c = ide_wait(device, IDE_TIME_OUT);
    
    		if (c & ATA_STAT_BUSY) {
    			printf("IDE read: device %d not ready\n", device);
    			break;
    		}
    #ifdef CONFIG_LBA48
    		if (lba48) {
    			/* write high bits */
    			ide_outb(device, ATA_SECT_CNT, 0);
    			ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
    #ifdef CONFIG_SYS_64BIT_LBA
    			ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
    			ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
    #else
    			ide_outb(device, ATA_LBA_MID, 0);
    			ide_outb(device, ATA_LBA_HIGH, 0);
    #endif
    		}
    #endif
    		ide_outb(device, ATA_SECT_CNT, 1);
    		ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
    		ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
    		ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
    
    #ifdef CONFIG_LBA48
    		if (lba48) {
    			ide_outb(device, ATA_DEV_HD,
    				 ATA_LBA | ATA_DEVICE(device));
    			ide_outb(device, ATA_COMMAND, ATA_CMD_READ_EXT);
    
    		} else
    #endif
    		{
    			ide_outb(device, ATA_DEV_HD, ATA_LBA |
    				 ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
    			ide_outb(device, ATA_COMMAND, ATA_CMD_READ);
    		}
    
    		udelay(50);
    
    		if (pwrsave) {
    			/* may take up to 4 sec */
    			c = ide_wait(device, IDE_SPIN_UP_TIME_OUT);
    			pwrsave = 0;
    		} else {
    			/* can't take over 500 ms */
    			c = ide_wait(device, IDE_TIME_OUT);
    		}
    
    		if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
    		    ATA_STAT_DRQ) {
    			printf("Error (no IRQ) dev %d blk " LBAF
    			       ": status %#02x\n", device, blknr, c);
    			break;
    		}
    
    		ide_input_data(device, buffer, ATA_SECTORWORDS);
    		(void) ide_inb(device, ATA_STATUS);	/* clear IRQ */
    
    		++n;
    		++blknr;
    		buffer += ATA_BLOCKSIZE;
    	}
    IDE_READ_E:
    	ide_led(DEVICE_LED(device), 0);	/* LED off      */
    	return n;
    }
    
    ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
    		const void *buffer)
    {
    	int device = block_dev->devnum;
    	ulong n = 0;
    	unsigned char c;
    
    #ifdef CONFIG_LBA48
    	unsigned char lba48 = 0;
    
    	if (blknr & 0x0000fffff0000000ULL) {
    		/* more than 28 bits used, use 48bit mode */
    		lba48 = 1;
    	}
    #endif
    
    	ide_led(DEVICE_LED(device), 1);	/* LED on       */
    
    	/* Select device
    	 */
    	ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
    
    	while (blkcnt-- > 0) {
    		c = ide_wait(device, IDE_TIME_OUT);
    
    		if (c & ATA_STAT_BUSY) {
    			printf("IDE read: device %d not ready\n", device);
    			goto WR_OUT;
    		}
    #ifdef CONFIG_LBA48
    		if (lba48) {
    			/* write high bits */
    			ide_outb(device, ATA_SECT_CNT, 0);
    			ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
    #ifdef CONFIG_SYS_64BIT_LBA
    			ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
    			ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
    #else
    			ide_outb(device, ATA_LBA_MID, 0);
    			ide_outb(device, ATA_LBA_HIGH, 0);
    #endif
    		}
    #endif
    		ide_outb(device, ATA_SECT_CNT, 1);
    		ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
    		ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
    		ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
    
    #ifdef CONFIG_LBA48
    		if (lba48) {
    			ide_outb(device, ATA_DEV_HD,
    				 ATA_LBA | ATA_DEVICE(device));
    			ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE_EXT);
    
    		} else
    #endif
    		{
    			ide_outb(device, ATA_DEV_HD, ATA_LBA |
    				 ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
    			ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE);
    		}
    
    		udelay(50);
    
    		/* can't take over 500 ms */
    		c = ide_wait(device, IDE_TIME_OUT);
    
    		if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
    		    ATA_STAT_DRQ) {
    			printf("Error (no IRQ) dev %d blk " LBAF
    			       ": status %#02x\n", device, blknr, c);
    			goto WR_OUT;
    		}
    
    		ide_output_data(device, buffer, ATA_SECTORWORDS);
    		c = ide_inb(device, ATA_STATUS);	/* clear IRQ */
    		++n;
    		++blknr;
    		buffer += ATA_BLOCKSIZE;
    	}
    WR_OUT:
    	ide_led(DEVICE_LED(device), 0);	/* LED off      */
    	return n;
    }
    
    #if defined(CONFIG_OF_IDE_FIXUP)
    int ide_device_present(int dev)
    {
    	if (dev >= CONFIG_SYS_IDE_MAXBUS)
    		return 0;
    	return ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1;
    }
    #endif
    
    U_BOOT_LEGACY_BLK(ide) = {
    	.if_typename	= "ide",
    	.if_type	= IF_TYPE_IDE,
    	.max_devs	= CONFIG_SYS_IDE_MAXDEVICE,
    	.desc		= ide_dev_desc,
    };