|
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. |