N
ich habs, was plymtacky wollte! die richtung in die es geht, hatte <os-developer> ja schon richtig vorgegeben. die adressen (also kopf usw.) muss man erst in die entsprechenden register schreiben. dann schickt man an das befehls-register den befehl 0x70 (SEEK) und er positioniert alles so, wie es in den adressmedienregistern steht.
ich hoffe, ihr seid mir nicht böse, wenn ich hier im ASM-Forum mit C-Code komme
Bsp in C:
// all hd-regs
#define HD_DATA_REG 0x1F0
#define HD_ERROR_REG 0x1F1 /* read */
#define HD_FEATURE_REG 0x1F1 /* write */
#define HD_SEC_COUNT_REG 0x1F2
#define HD_SEC_NUM_REG 0x1F3
#define HD_CYL_NUM_LOW_REG 0x1F4
#define HD_CYL_NUM_HI_REG 0x1F5
#define HD_DRIVE_REG 0x1F6
#define HD_STATE_REG 0x1F7 /* read */
#define HD_COM_REG 0x1F7 /* write */
// flags in the state-reg
#define HD_ERROR 1
#define HD_INDEX 2
#define HD_CORRECTED_DATA 4
#define HD_DATA_REQUEST 8
#define HD_DRIVE_SEEK_COMPLETE 16
#define HD_DRIVE_FAULT 32
#define HD_DRIVE_READY 64
#define HD_BUSY 128
// commands
#define HD_READ_SEC_RETRY 0x20
#define HD_READ_SEC 0x21
#define HD_WRITE_SEC_RETRY 0x30
#define HD_WRITE_SEC 0x31
#define HD_SEEK 0x70
#define HD_READ_MULTIPLE 0xC4
#define HD_WRITE_MULTIPLE 0xC5
#define HD_READ_DMA_RETRY 0xC8
#define HD_READ_DMA 0xC9
#define HD_WRITE_DMA_RETRY 0xCA
#define HD_WRITE_DMA 0xCB
#define HD_STANDBY 0xE2
#define HD_SLEEP 0xE6
#define HD_IDENTIFY_DEVICE 0xEC
void main (void) {
outb (HD_SEC_COUNT_REG, 1);
outb (HD_SEC_NUM_REG, 1);
outb (HD_CYL_NUM_LOW_REG, 0);
outb (HD_CYL_NUM_HI_REG, 0);
outb (HD_DRIVE_REG, 128|32|(0<<4)|1);
outb (HD_COM_REG, HD_SEEK);
}
(outb ist eine methode zum "outen" eines bytes an den angegebenen port)
wenn man einen sektor lesen will, kann man das so machen:
//... hier her noch die defs von oben
void insw (int port, void far * buffer, int words) {
asm Push Di
asm ClD
asm Mov Dx,port
asm Mov Cx,words
asm Mov Di,Word Ptr [buffer]
asm Mov Ax,Word Ptr [buffer+2]
asm Mov Es,Ax
insw_loop:
asm In Ax,Dx
asm StoSW
asm Loop insw_loop
asm Pop Di
}
void main (void) {
int i;
int retries = 10000;
char buffer[512];
outb (HD_SEC_COUNT_REG, 1);
outb (HD_SEC_NUM_REG, 1);
outb (HD_CYL_NUM_LOW_REG, 0);
outb (HD_CYL_NUM_HI_REG, 0);
outb (HD_DRIVE_REG, 128|32|(0<<4)|1);
outb (HD_COM_REG, HD_READ_SEC);
do {
i = (unsigned) inb(HD_STATE_REG);
if (i & HD_BUSY) continue;
if (i & HD_DATA_REQUEST) goto ok_to_read;
} while (--retries > 0);
// output error-msg
return;
ok_to_read:
insw (HD_DATA_REG, buffer, 256);
for (i = 0; i < 512; ++i)
printf ("%c", *((char*)buffer+i));
}
(liest den boot-sector der ersten festplatte)
viel spaß damit
cu todo