|
Hauptseite - Welches System? - Hardware - Software - Emulatoren - |
Internet MausNet Programmieren Verweise Über |
Das folgende Beispiel ist ein Minimalrumpf für einen BOS Treiber, der für jede Funktion eine C Funktion aufruft und sämtliche Parameter auf den Stack legt. Damit könnte der Assemblerrumpf als Wrapper zu einer Implementierung in C dienen.
.EXPORT bos_functions
.IMPORT BosInit, BosDevInit
.IMPORT BosOpen, BosClose, BosRead, BosWrite
.IMPORT BosSeek, BosStatus, BosIoctl
.IMPORT BosStartaudio, BosStopaudio, BosSetsongtime
.IMPORT BosGettoc, BosDiscinfo
TEXT
entry_point:
; Aktionen, die zur Initialisierung des Treibers noetig sind
jsr BosInit
; Liefere den Zeiger fuer die Initialisierung des Geraetes
move.l #init_device_p,d0
rts
init_device:
move.w d1,-(sp) ; DMA Kanal
move.w d0,-(sp) ; physikalischen Laufwerksbuchstaben
jsr BosDevInit
addq.l #8,sp
rts
; Fuer diese Functionen zeigt a0 auf den Bos Header des Geraetes
; Die Parameter liegen auf dem Stack ab 4(sp)
open:
move.l a0,-(sp) ; META_BOS_HEADER *bosheader
jsr BosOpen
addq.l #4,sp
rts
close:
move.l a0,-(sp) ; META_BOS_HEADER *bosheader
jsr BosClose
addq.l #4,sp
rts
read:
move.l a0,-(sp) ; META_BOS_HEADER *bosheader
jsr BosRead
addq.l #4,sp
rts
write:
move.l a0,-(sp) ; META_BOS_HEADER *bosheader
jsr BosWrite
addq.l #4,sp
rts
seek:
move.l a0,-(sp) ; META_BOS_HEADER *bosheader
jsr BosSeek
addq.l #4,sp
rts
status:
move.l a0,-(sp) ; META_BOS_HEADER *bosheader
jsr BosStatus
addq.l #4,sp
rts
ioctl:
move.l a0,-(sp) ; META_BOS_HEADER *bosheader
jsr BosIoctl
addq.l #4,sp
rts
startaudio:
move.l a0,-(sp) ; META_BOS_HEADER *bosheader
jsr BosStartaudio
addq.l #4,sp
rts
stopaudio:
move.l a0,-(sp) ; META_BOS_HEADER *bosheader
jsr BosStopaudio
addq.l #4,sp
rts
setsongtime:
move.l a0,-(sp) ; META_BOS_HEADER *bosheader
jsr BosSetsongtime
addq.l #4,sp
rts
gettoc:
move.l a0,-(sp) ; META_BOS_HEADER *bosheader
jsr BosGettoc
addq.l #4,sp
rts
discinfo:
move.l a0,-(sp) ; META_BOS_HEADER *bosheader
jsr BosDiscinfo
addq.l #4,sp
rts
DATA
init_device_p:
dc.l init_device
bos_functions:
dc.l $ffffffff
dc.l open
dc.l close
dc.l read
dc.l write
dc.l seek
dc.l status
dc.l ioctl
dc.l $ffffffff
dc.l $ffffffff
dc.l $ffffffff
dc.l startaudio
dc.l stopaudio
dc.l setsongtime
dc.l gettoc
dc.l discinfo
END
Diese Assemblerfunktionen speichern die zusätzlichen Parameter der Register auf dem Stack, ohne die schon vorhandene Parameter umzusortieren. Damit findet die C Funktionen auch den Opcode der XBIOS Funktion aus dem Trap und die Rücksprungadresse dort vor. Damit hat jede C Funktion die Parameter bosheader (aus A0), die Rücksprungadresse ret für den XBIOS Trap und den XBIOS Opcode. Die Parameter ret und opcode sind deshalb ohne Bedeutung und müssen ignoriert werden.
xyz(META_BOS_HEADER *bosheader, long ret, int opcode,
Der Rumpf für eine C Implementierung würde damit wie folgt aussehen:
#include <string.h>
#include <metados.h>
extern META_BOS_FUNCTIONS bos_functions;
static META_BOS_HEADER BosHeader;
void BosInit(void)
{
}
long cdecl BosDevInit(unsigned int PhysDrive, unsigned int PhysChannel)
{
memset(&BosHeader, 0, sizeof(BosHeader));
BosHeader.phys_letter = PhysDrive;
BosHeader.dma_channel = PhysChannel;
BosHeader.functions = &bos_functions;
strcpy(BosHeader.name, "DISKIMAGE");
/* Liefere den BOS Header (oder einen negativen Fehlercode, falls noetig) */
return((long)&BosHeader);
}
long cdecl BosOpen(META_BOS_HEADER *bosheader, long ret, int opcode,
META_DRVINFO *metaopen)
{
metaopen->mdr_name = bosheader->name;
metaopen->res[0] = 0;
metaopen->res[1] = 0;
metaopen->res[2] = 0;
return(0);
}
long cdecl BosClose(META_BOS_HEADER *bosheader)
{
return(0);
}
long cdecl BosRead(META_BOS_HEADER *bosheader, long ret, int opcode,
void *buffer, unsigned long first, unsigned short count)
{
/* <count> Bloecke von <first> Block nach <buffer> lesen */
return(-32);
}
long cdecl BosWrite(META_BOS_HEADER *bosheader, long ret, int opcode,
void *buffer, unsigned long first, unsigned short count)
{
/* <count> Bloecke ab <first> Block von <buffer> schreiben */
return(-32);
}
long cdecl BosSeek(META_BOS_HEADER *bosheader, long ret, int opcode,
unsigned long offset)
{
/* Schreib-/Lesezeiger auf Block <offset> setzen */
return(-32);
}
long cdecl BosStatus(META_BOS_HEADER *bosheader, long ret, int opcode,
META_BOS_STATUS *extended)
{
/* Status des GEraewtss liefern. -1 = Fehler,
bit 1: Device Busy
bit 2: Medienwechsel
bit 7: Timeout
bit 15: Error
*/
return(-32);
}
long cdecl BosIoctl(META_BOS_HEADER *bosheader, long ret, int opcode,
unsigned long magic, unsigned short ioctlopcode, void *buffer)
{
/* Geraetespezifische Aktion ausfuehren */
return(-32);
}
long cdecl BosStartaudio(META_BOS_HEADER *bosheader, long ret, int opcode,
unsigned short dummy, unsigned char *tracks)
{
/* Abspielen von audio starten */
return(-32);
}
long cdecl BosStopaudio(META_BOS_HEADER *bosheader)
{
/* Abspielen von audio beenden */
return(-32);
}
long cdecl BosSetsongtime(META_BOS_HEADER *bosheader, long ret, int opcode,
unsigned short dummy, unsigned long start, unsigned long end)
{
/* Abspeielen von Audio starten */
return(-32);
}
long cdecl BosGettoc(META_BOS_HEADER *bosheader, long ret, int opcode,
unsigned short dummy, CD_TOC_ENTRY *tocentry)
{
/* Inhaltsverzeichnis lesen */
return(-32);
}
long cdecl BosDiscinfo(META_BOS_HEADER *bosheader, long ret, int opcode,
CD_DISC_INFO *discinfo)
{
/* Informationen ueber CD erfragen */
return(-32);
}
|
English version not yet available. |