OT: C-Frage: Pointer to Pointer

12/04/2011 - 21:07 von Jens Kallup | Report spam
Hallo,

ich versuche gerade meine weiteren Versuche mit den BIOS Sektoren zu
lesen, da mir die IRQ ATAPI Treiber programmierung nicht so recht
gelingen will bzw. mich überfordert - wer Material und Sources hat -
immer her damit.
Also, folgendes ist gegeben (in C):

void print_status(unsigned short c)
{
switch (c)
{
case 0x00: printk("successful completion"); break;
case 0x01: printk("invalid function in AH or invalid parameter"); break;
case 0x02: printk("address mark not found"); break;
case 0x03: printk("disk write-protected"); break;
case 0x04: printk("sector not found/read error"); break;
case 0x05: printk("reset failed (hard disk)"); break;
case 0x06: printk("disk changed (floppy)"); break;
case 0x07: printk("drive parameter activity failed (hard disk)"); break;
default: printk("other disk error"); break;
}
printk("");
/*
08h DMA overrun
09h data boundary error (attempted DMA across 64K boundary or >80h
sectors)
0Ah bad sector detected (hard disk)
0Bh bad track detected (hard disk)
0Ch unsupported track or invalid media
0Dh invalid number of sectors on format (PS/2 hard disk)
0Eh control data address mark detected (hard disk)
0Fh DMA arbitration level out of range (hard disk)
10h uncorrectable CRC or ECC error on read
11h data ECC corrected (hard disk)
20h controller failure
31h no media in drive (IBM/MS INT 13 extensions)
32h incorrect drive type stored in CMOS (Compaq)
40h seek failed
80h timeout (not ready)
AAh drive not ready (hard disk)
B0h volume not locked in drive (INT 13 extensions)
B1h volume locked in drive (INT 13 extensions)
B2h volume not removable (INT 13 extensions)
B3h volume in use (INT 13 extensions)
B4h lock count exceeded (INT 13 extensions)
B5h valid eject request failed (INT 13 extensions)
B6h volume present but read protected (INT 13 extensions)
BBh undefined error (hard disk)
CCh write fault (hard disk)
E0h status register error (hard disk)
FFh sense operation failed (hard disk)
*/
}


#define BIOSCALLBUFFER 0x78000 /* Buffer to store temporary data for
any Int386() call */
#define BIOSCALLBUFSEGMENT 0x7800 /* Buffer to store temporary data for
any Int386() call */
#define BIOSCALLBUFOFFSET 0x0000 /* Buffer to store temporary data for
any Int386() call */
#define FILESYSBUFFER 0x80000 /* Buffer to store file system data (e.g.
cluster buffer for FAT) */
#define DISKREADBUFFER 0x90000 /* Buffer to store data read in from the
disk via the BIOS */

...
unsigned short *Ptr = (unsigned short*)(DISKREADBUFFER);
unsigned short *ptr ;
unsigned short *buffer;
int b;

ptr = memset(Ptr,1,0x18);
memset(buffer,1,4096); // speicher block ausfüllen

regsin.b.ah = 0x42;
regsin.b.dl = 0x80;
regsin.w.ds = DISKREADBUFFER;
regsin.w.si = 0;

ptr[0x02] = 1;
ptr[0x04] = *buffer; // <.. hier
ptr[0x08] = 0;

int386(0x13,&regsin,&regsout);

print_status(regsout.b.ah);


printk("1data: %d , %d",ptr[0x00], ptr[0x01]);
printk("2data: %d , 0x%x",ptr[0x02], ptr[0x04]);
printk("3data: %d , %d",ptr[0x08], ptr[0x10]);
printk("7data: %d , %d",ptr[0x18], (int)ptr[0x18]+256);

for (b = 0; b < 256; b++)
printk("%c",buffer[b]); // hier erhalte ich nur 0x01 zeichen


in ralf brown's int liste finde ich folgendes:

IBM/MS INT 13 Extensions - EXTENDED READ

AH = 42h
DL = drive number
DS:SI -> disk address packet (see #00272)

Format of disk address packet:

Offset Size Description (Table 00272)
00h BYTE size of packet (10h or 18h)
01h BYTE reserved (0)
02h WORD number of blocks to transfer (max 007Fh for Phoenix EDD)

04h DWORD -> transfer buffer // hier wie zu adressieren?

08h QWORD starting absolute block number
(for non-LBA devices, compute as
(Cylinder*NumHeads + SelectedHead) * SectorPerTrack +
SelectedSector - 1
10h QWORD (EDD-3.0, optional) 64-bit flat address of transfer buffer;
used if DWORD at 04h is FFFFh:FFFFh


Frage: Wie komme ich an die Daten eines Sektors?
Also der Pointer darauf müsste doch im offset 0x04h stehen?
Das wàre dann ein Pointer auf Pointer also DS:SI->04h ???
wie programmiert man sowas?

Danke und Gruß
Jens
 

Lesen sie die antworten

#1 Vinzent Hoefler
12/04/2011 - 21:43 | Warnen spam
Jens Kallup wrote:

ich versuche gerade meine weiteren Versuche mit den BIOS Sektoren zu
lesen, da mir die IRQ ATAPI Treiber programmierung nicht so recht
gelingen will bzw. mich überfordert - wer Material und Sources hat -
immer her damit.
Also, folgendes ist gegeben (in C):



Welches Speichermodell benutzt Dein C-Compiler hier?

#define BIOSCALLBUFFER 0x78000 /* Buffer to store temporary data for
any Int386() call */
#define BIOSCALLBUFSEGMENT 0x7800 /* Buffer to store temporary data for
any Int386() call */
#define BIOSCALLBUFOFFSET 0x0000 /* Buffer to store temporary data for
any Int386() call */
#define FILESYSBUFFER 0x80000 /* Buffer to store file system data (e.g.
cluster buffer for FAT) */
#define DISKREADBUFFER 0x90000 /* Buffer to store data read in from the
disk via the BIOS */



Versteh ich das richtig? Du definierst Dir hier einfach wild irgendwelche "Adressen"?

...
unsigned short *Ptr = (unsigned short*)(DISKREADBUFFER);
unsigned short *ptr ;



Ich schàtze mal, damit dürfte "sizeof (*ptr) == 2" gelten.

unsigned short *buffer;
int b;

ptr = memset(Ptr,1,0x18);
memset(buffer,1,4096); // speicher block ausfüllen

regsin.b.ah = 0x42;
regsin.b.dl = 0x80;
regsin.w.ds = DISKREADBUFFER;



In DS steht jetzt 0, da das nur ein 16-Bit-Wert ist und die oberen Bits von 0x90000
damit abgeschnitten werden. In SI ebenso. Auf gut deutsch: Du übergibst NULL als
Buffer und übergibst DOS damit die Interruptvektortabelle als "disk address packet".

regsin.w.si = 0;

ptr[0x02] = 1;
ptr[0x04] = *buffer; // <.. hier
ptr[0x08] = 0;



Hier adressierst Du ein short-Array. D.h., die Indizes stimmen nicht mit den
eigentlichen Adress-Offset überein.

int386(0x13,&regsin,&regsout);

print_status(regsout.b.ah);


printk("1data: %d , %d",ptr[0x00], ptr[0x01]);
printk("2data: %d , 0x%x",ptr[0x02], ptr[0x04]);
printk("3data: %d , %d",ptr[0x08], ptr[0x10]);
printk("7data: %d , %d",ptr[0x18], (int)ptr[0x18]+256);



Selbes hier.

for (b = 0; b < 256; b++)
printk("%c",buffer[b]); // hier erhalte ich nur 0x01 zeichen


in ralf brown's int liste finde ich folgendes:

IBM/MS INT 13 Extensions - EXTENDED READ

AH = 42h
DL = drive number
DS:SI -> disk address packet (see #00272)

Format of disk address packet:

Offset Size Description (Table 00272)
00h BYTE size of packet (10h or 18h)
01h BYTE reserved (0)
02h WORD number of blocks to transfer (max 007Fh for Phoenix EDD)

04h DWORD -> transfer buffer // hier wie zu adressieren?

08h QWORD starting absolute block number
(for non-LBA devices, compute as
(Cylinder*NumHeads + SelectedHead) * SectorPerTrack +
SelectedSector - 1
10h QWORD (EDD-3.0, optional) 64-bit flat address of transfer buffer;
used if DWORD at 04h is FFFFh:FFFFh


Frage: Wie komme ich an die Daten eines Sektors?
Also der Pointer darauf müsste doch im offset 0x04h stehen?



Richtig. Im OFFSET. Der basiert allerdings auf 8-Bit-Quantitàten.

Das wàre dann ein Pointer auf Pointer also DS:SI->04h ???
wie programmiert man sowas?



Am besten mit structs. Etwa so:

#include <stdint.h>

...

typedef struct {
int8_t size_of_packet;
int8_t reserved;
int16_t block_count;
char* transfer_buffer;
...
} disk_address_packet_t;

Ob und welche Compilerpragmas Du dann anwenden mußt, damit der Compiler die Struktur
auch exakt so erzeugt, mußt Du Deiner Compilerdokumentation entnehmen.

Danach müßtest Du eine solche Variable anlegen, sie passend befüllen und ihre Adresse
nach DS:SI bekommen.


Vinzent.

A C program is like a fast dance on a newly waxed dance floor by people carrying
razors.

Ähnliche fragen