📄 ide.c
字号:
/* * Copyright (c) 2006 Atmark Techno, Inc. All Rights Reserved. */#include <target/io.h>#define MULTIPLE 3#define TIMEOUT 50000#define IDE_DATA 0x62000000#define IDE_ERROR 0x62000002#define IDE_FEAUTURES 0x62000002#define IDE_SECTOR_COUNT 0x62000004#define IDE_SECTOR_NUMBER 0x62000006#define IDE_SECTOR_CYLINDER_LOW 0x62000008#define IDE_SECTOR_CYLINDER_HIGH 0x6200000a#define IDE_DEVICE_HEAD 0x6200000c#define IDE_STATUS 0x6200000e#define IDE_COMMAND 0x6200000e#define IDE_ALTERNATE_STATUS 0x6200002c#define IDE_DEVICE_CONTROL 0x6200002c#define IDE_STATUS_BUSY 0x80#define IDE_STATUS_DRDY 0x40#define IDE_STATUS_DRQ 0x08#define IDE_STATUS_ERR 0x01#define IDE_COMMAND_READ_SECTORS 0x20#define IDE_COMMAND_IDLE 0xe3#define IDE_COMMAND_IDENTIFY 0xec#define IDE_DEVICE_CONTROL_SRST 0x04#define IDE_DEVICE_CONTROL_NIEN 0x02#define IDE_LBA 0x40#define ide_inb(port) (*(volatile unsigned char *)(port))#define ide_inw(port) (*(volatile unsigned short *)(port))#define ide_outb(b,port) (*(volatile unsigned char *)(port)=(b))#define ide_outw(w,port) (*(volatile unsigned short *)(port)=(w))#define delay(count) {int d;for(d=0;d<(count*MULTIPLE);d++);}static int wait_nbusy_ndrq (void){ int i; for (i = 0; i < TIMEOUT && (ide_inb (IDE_ALTERNATE_STATUS) & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)); i++) { delay (100); } if (i >= TIMEOUT) { return -1; } return 0;}static int wait_nbusy (void){ int i; for (i = 0; i < TIMEOUT && (ide_inb (IDE_ALTERNATE_STATUS) & IDE_STATUS_BUSY); i++) { delay (100); } if (i >= TIMEOUT) { return -1; } return 0;}static int wait_ready (void){ int i; for (i = 0; i < TIMEOUT && !(ide_inb (IDE_ALTERNATE_STATUS) & IDE_STATUS_DRDY); i++) { delay (100); } if (i >= TIMEOUT) { return -1; } return 0;}static int ide_reset (void){ int ret; unsigned char error; ide_outb (IDE_DEVICE_CONTROL_SRST | IDE_DEVICE_CONTROL_NIEN, IDE_DEVICE_CONTROL); delay (40000); ide_outb (IDE_DEVICE_CONTROL_NIEN, IDE_DEVICE_CONTROL); delay (40000); ret = wait_nbusy (); if (ret) { return ret; } error = ide_inb (IDE_ERROR); if (error != 0 && error != 1) { return -1; } return 0;}static int ide_device_selection (int dev){ int ret; ret = wait_nbusy_ndrq (); if (ret) { return ret; } ide_outb (IDE_DEVICE_CONTROL_NIEN, IDE_DEVICE_CONTROL); ide_outb (dev << 4, IDE_DEVICE_HEAD); delay (100); return wait_nbusy_ndrq ();}static int ide_register_check (void){ ide_outb (0x55, IDE_SECTOR_CYLINDER_LOW); ide_outb (0xaa, IDE_SECTOR_CYLINDER_HIGH); if (ide_inb (IDE_SECTOR_CYLINDER_LOW) != 0x55) { return -1; } if (ide_inb (IDE_SECTOR_CYLINDER_HIGH) != 0xaa) { return -1; } return 0;}static int ide_get_data (unsigned char *buf, int count){ int ret, i; unsigned short data; while (count--) { ret = wait_nbusy (); if (ret) { return ret; } if (ide_inb (IDE_ALTERNATE_STATUS) & IDE_STATUS_ERR) { return -1; } for (i = 0; i < 256; i++) { data = ide_inw (IDE_DATA); *buf++ = data & 0xff; *buf++ = data >> 8; } } return 0;}static void ide_fix_string (unsigned char *dest, unsigned char *src, int num){ int i; for (i = 0; i < num; i+= 2) { *dest++ = *(src + 1); *dest++ = *src; src += 2; } while (*--dest == (' ')) ; ++dest; *dest++ = ' '; *dest++ = '\0';}static int ide_identify_device (int dev){ int ret; unsigned short buf[256]; unsigned char name[42]; ret = ide_device_selection (dev); if (ret) { return ret; } ret = wait_ready (); if (ret) { return ret; } ide_outb (IDE_COMMAND_IDENTIFY, IDE_COMMAND); delay (100); ret = ide_get_data ((unsigned char *)buf, 1); if (ret) { return ret; } if (*buf & 0x04) { return -1; } hprintf ("Disk drive detected: "); ide_fix_string (name, (unsigned char *)&buf[27], 40); hprintf ("%s", name); ide_fix_string (name, (unsigned char *)&buf[23], 8); hprintf ("%s", name); ide_fix_string (name, (unsigned char *)&buf[10], 20); hprintf ("%s", name); hprintf ("\n"); return 0;}static int ide_idle (int dev){ int ret; ret = ide_device_selection (0); if (ret) { return ret; } ret = wait_ready (); if (ret) { return ret; } ide_outb (0x00, IDE_SECTOR_COUNT); ide_outb (IDE_COMMAND_IDLE, IDE_COMMAND); delay (100); return wait_nbusy_ndrq ();}int ide_detect_devices (){ int ret; ret = ide_reset (); if (ret) { return ret; } ret = ide_device_selection (0); if (ret) { return ret; } ret = ide_register_check (); if (ret) { return ret; } return ide_identify_device (0);}int ide_startup_devices (void){ return ide_idle (0);}int ide_read_sectors (int dev, unsigned long lba, unsigned char *buf, int count){ int ret; ret = ide_device_selection (dev); if (ret) { return ret; } ret = wait_ready (); if (ret) { return ret; } ide_outb (count, IDE_SECTOR_COUNT); ide_outb (lba & 0xff, IDE_SECTOR_NUMBER); ide_outb ((lba & 0xff00) >> 8, IDE_SECTOR_CYLINDER_LOW); ide_outb ((lba & 0xff0000) >> 16, IDE_SECTOR_CYLINDER_HIGH); ide_outb (IDE_LBA | (dev << 4) | ((lba & 0xf000000) >> 24), IDE_DEVICE_HEAD); ide_outb (IDE_COMMAND_READ_SECTORS, IDE_COMMAND); delay (100); return ide_get_data (buf, count);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -