diff --git a/XTMax/Drivers/.gitattributes b/XTMax/Drivers/.gitattributes new file mode 100644 index 0000000..4cab1f4 --- /dev/null +++ b/XTMax/Drivers/.gitattributes @@ -0,0 +1,2 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/BCC.EXE b/XTMax/Drivers/Driver_Build_Tools/BCC31/BCC.EXE new file mode 100644 index 0000000..3b2eed1 Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/BCC31/BCC.EXE differ diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/DPMI16BI.OVL b/XTMax/Drivers/Driver_Build_Tools/BCC31/DPMI16BI.OVL new file mode 100644 index 0000000..69f0e09 Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/BCC31/DPMI16BI.OVL differ diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/DPMILOAD.EXE b/XTMax/Drivers/Driver_Build_Tools/BCC31/DPMILOAD.EXE new file mode 100644 index 0000000..17881fa Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/BCC31/DPMILOAD.EXE differ diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/DPMIMEM.DLL b/XTMax/Drivers/Driver_Build_Tools/BCC31/DPMIMEM.DLL new file mode 100644 index 0000000..1d24230 Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/BCC31/DPMIMEM.DLL differ diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/CONIO.H b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/CONIO.H new file mode 100644 index 0000000..274d37f --- /dev/null +++ b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/CONIO.H @@ -0,0 +1,155 @@ +/* conio.h + + Direct MSDOS console input/output. + + Copyright (c) 1987, 1992 by Borland International + All Rights Reserved. +*/ + +#if !defined(__CONIO_H) +#define __CONIO_H + +#if !defined(___DEFS_H) +#include <_defs.h> +#endif + +#if !defined(_Windows) + +#define _NOCURSOR 0 +#define _SOLIDCURSOR 1 +#define _NORMALCURSOR 2 + +struct text_info { + unsigned char winleft; + unsigned char wintop; + unsigned char winright; + unsigned char winbottom; + unsigned char attribute; + unsigned char normattr; + unsigned char currmode; + unsigned char screenheight; + unsigned char screenwidth; + unsigned char curx; + unsigned char cury; +}; + +enum text_modes { LASTMODE=-1, BW40=0, C40, BW80, C80, MONO=7, C4350=64 }; + +#if !defined(__COLORS) +#define __COLORS + +enum COLORS { + BLACK, /* dark colors */ + BLUE, + GREEN, + CYAN, + RED, + MAGENTA, + BROWN, + LIGHTGRAY, + DARKGRAY, /* light colors */ + LIGHTBLUE, + LIGHTGREEN, + LIGHTCYAN, + LIGHTRED, + LIGHTMAGENTA, + YELLOW, + WHITE +}; +#endif + +#define BLINK 128 /* blink bit */ + +extern int _Cdecl directvideo; +extern int _Cdecl _wscroll; + +#endif /* !_Windows */ + +#ifdef __cplusplus +extern "C" { +#endif + +void _Cdecl clreol( void ); +void _Cdecl clrscr( void ); +void _Cdecl gotoxy( int __x, int __y ); +int _Cdecl wherex( void ); +int _Cdecl wherey( void ); +int _Cdecl getch( void ); +int _Cdecl getche( void ); +int _Cdecl kbhit( void ); +int _Cdecl putch( int __c ); + +#ifndef _PORT_DEFS +unsigned char _Cdecl inportb( unsigned __portid ); +unsigned _Cdecl inport ( unsigned __portid ); +int _Cdecl inp( unsigned __portid ); +unsigned _Cdecl inpw( unsigned __portid ); +void _Cdecl outportb( unsigned __portid, unsigned char __value ); +void _Cdecl outport ( unsigned __portid, unsigned __value ); +int _Cdecl outp( unsigned __portid, int __value ); +unsigned _Cdecl outpw( unsigned __portid, unsigned __value ); +#endif /* !_PORT_DEFS */ + +#if !defined(_Windows) + +void _Cdecl delline( void ); +int _Cdecl gettext( int __left, int __top, + int __right, int __bottom, + void *__destin); +void _Cdecl gettextinfo (struct text_info *__r ); +void _Cdecl highvideo( void ); +void _Cdecl insline( void ); +void _Cdecl lowvideo( void ); +int _Cdecl movetext( int __left, int __top, + int __right, int __bottom, + int __destleft, int __desttop ); +void _Cdecl normvideo( void ); +int _Cdecl puttext( int __left, int __top, + int __right, int __bottom, + void *__source ); +void _Cdecl textattr( int __newattr ); +void _Cdecl textbackground( int __newcolor ); +void _Cdecl textcolor( int __newcolor ); +void _Cdecl textmode( int __newmode ); +void _Cdecl window( int __left, int __top, int __right, int __bottom); + +void _Cdecl _setcursortype( int __cur_t ); +char * _Cdecl cgets( char *__str ); +int _Cdecl cprintf( const char *__format, ... ); +int _Cdecl cputs( const char *__str ); +int _Cdecl cscanf( const char *__format, ... ); +char * _Cdecl getpass( const char *__prompt ); +int _Cdecl ungetch( int __ch ); + +#endif /* !_Windows */ + +#ifndef _PORT_DEFS +#define _PORT_DEFS + + /* These are in-line functions. These prototypes just clean up + some syntax checks and code generation. + */ +unsigned char _Cdecl __inportb__ (unsigned __portid); +unsigned _Cdecl __inportw__ (unsigned __portid); +unsigned char _Cdecl __outportb__(unsigned __portid, unsigned char __value); +unsigned _Cdecl __outportw__(unsigned __portid, unsigned __value); + +#define inportb(__portid) __inportb__(__portid) +#define outportb(__portid, __value) ((void) __outportb__(__portid, __value)) +#define inport(__portid) __inportw__(__portid) +#define outport(__portid, __value) ((void) __outportw__(__portid, __value)) + +/* MSC-compatible macros for port I/O */ +#define inp(__portid) __inportb__ (__portid) +#define outp(__portid, __value) __outportb__(__portid, (unsigned char)__value) +#define inpw(__portid) __inportw__ (__portid) +#define outpw(__portid, __value) __outportw__(__portid, __value) + +#endif /* _PORT_DEFS */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __CONIO_H */ diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/DOS.H b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/DOS.H new file mode 100644 index 0000000..acf5cdc --- /dev/null +++ b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/DOS.H @@ -0,0 +1,520 @@ +/* dos.h + + Defines structs, unions, macros, and functions for dealing + with MSDOS and the Intel iAPX86 microprocessor family. + + Copyright (c) 1987, 1992 by Borland International + All Rights Reserved. +*/ +#ifndef __DOS_H +#define __DOS_H + +#if !defined(___DEFS_H) +#include <_defs.h> +#endif + +#if !defined(_RTLDLL) +extern int _Cdecl errno; +extern int _Cdecl _doserrno; +#else + +#ifdef __cplusplus +extern "C" { +#endif +int far * far _Cdecl __getErrno(void); +int far * far _Cdecl __getDOSErrno(void); +#ifdef __cplusplus +} +#endif + +#define errno (*__getErrno()) +#define _doserrno (*__getDOSErrno()) +#endif + +#ifndef __DLL__ + +/* Variables */ +extern int const _Cdecl _8087; +extern int _Cdecl _argc; +extern char **_Cdecl _argv; +extern char **_Cdecl environ; + +extern unsigned _Cdecl _psp; +extern unsigned _Cdecl _heaplen; +extern unsigned char _Cdecl _osmajor; +extern unsigned char _Cdecl _osminor; +extern unsigned _Cdecl _stklen; +extern unsigned _Cdecl _fpstklen; +extern unsigned _Cdecl _version; +extern unsigned _Cdecl _osversion; /* MSC name for _version */ + +#endif /* __DLL__*/ + + +#define FA_NORMAL 0x00 /* Normal file, no attributes */ +#define FA_RDONLY 0x01 /* Read only attribute */ +#define FA_HIDDEN 0x02 /* Hidden file */ +#define FA_SYSTEM 0x04 /* System file */ +#define FA_LABEL 0x08 /* Volume label */ +#define FA_DIREC 0x10 /* Directory */ +#define FA_ARCH 0x20 /* Archive */ + +/* MSC names for file attributes */ + +#define _A_NORMAL 0x00 /* Normal file, no attributes */ +#define _A_RDONLY 0x01 /* Read only attribute */ +#define _A_HIDDEN 0x02 /* Hidden file */ +#define _A_SYSTEM 0x04 /* System file */ +#define _A_VOLID 0x08 /* Volume label */ +#define _A_SUBDIR 0x10 /* Directory */ +#define _A_ARCH 0x20 /* Archive */ + +#define NFDS 20 /* Maximum number of fds */ + +struct fcb { + char fcb_drive; /* 0 = default, 1 = A, 2 = B */ + char fcb_name[8]; /* File name */ + char fcb_ext[3]; /* File extension */ + short fcb_curblk; /* Current block number */ + short fcb_recsize; /* Logical record size in bytes */ + long fcb_filsize; /* File size in bytes */ + short fcb_date; /* Date file was last written */ + char fcb_resv[10]; /* Reserved for DOS */ + char fcb_currec; /* Current record in block */ + long fcb_random; /* Random record number */ +}; + +struct xfcb { + char xfcb_flag; /* Contains 0xff to indicate xfcb */ + char xfcb_resv[5];/* Reserved for DOS */ + char xfcb_attr; /* Search attribute */ + struct fcb xfcb_fcb; /* The standard fcb */ +}; + +struct COUNTRY { + int co_date; + char co_curr[5]; + char co_thsep[2]; + char co_desep[2]; + char co_dtsep[2]; + char co_tmsep[2]; + char co_currstyle; + char co_digits; + char co_time; + long co_case; + char co_dasep[2]; + char co_fill[10]; +}; + +#if defined(__MSC) && !defined(__cplusplus) +struct DOSERROR { + int exterror; + char class; + char action; + char locus; +}; +#else +struct DOSERROR { + int de_exterror; + char de_class; + char de_action; + char de_locus; +}; +#endif /* __MSC and not C++ */ + +struct dfree { + unsigned df_avail; + unsigned df_total; + unsigned df_bsec; + unsigned df_sclus; +}; + +struct diskfree_t { + unsigned total_clusters; + unsigned avail_clusters; + unsigned sectors_per_cluster; + unsigned bytes_per_sector; +}; + +struct fatinfo { + char fi_sclus; + char fi_fatid; + unsigned fi_nclus; + int fi_bysec; +}; + +struct devhdr { + long dh_next; /* Next device pointer */ + short dh_attr; /* Attributes */ + unsigned short dh_strat; /* Driver strategy routine */ + unsigned short dh_inter; /* Driver interrupt routine */ + char dh_name[8]; /* Device name */ +}; + +struct time { + unsigned char ti_min; /* Minutes */ + unsigned char ti_hour; /* Hours */ + unsigned char ti_hund; /* Hundredths of seconds */ + unsigned char ti_sec; /* Seconds */ +}; + +struct dostime_t { + unsigned char hour; /* Hours */ + unsigned char minute; /* Minutes */ + unsigned char second; /* Seconds */ + unsigned char hsecond; /* Hundredths of seconds */ +}; + +struct date { + int da_year; /* Year - 1980 */ + char da_day; /* Day of the month */ + char da_mon; /* Month (1 = Jan) */ +}; + +struct dosdate_t { + unsigned char day; /* 1-31 */ + unsigned char month; /* 1-12 */ + unsigned int year; /* 1980 - 2099 */ + unsigned char dayofweek;/* 0 - 6 (0=Sunday) */ +}; + +#ifndef _REG_DEFS +#define _REG_DEFS + +struct WORDREGS { + unsigned int ax, bx, cx, dx, si, di, cflag, flags; +}; + +struct BYTEREGS { + unsigned char al, ah, bl, bh, cl, ch, dl, dh; +}; + +union REGS { + struct WORDREGS x; + struct BYTEREGS h; +}; + +struct SREGS { + unsigned int es; + unsigned int cs; + unsigned int ss; + unsigned int ds; +}; + +struct REGPACK { + unsigned r_ax, r_bx, r_cx, r_dx; + unsigned r_bp, r_si, r_di, r_ds, r_es, r_flags; +}; + +#endif /* _REG_DEFS */ + +typedef struct { + char ds_drive; /* do not change */ + char ds_pattern [13]; /* these fields, */ + char ds_reserved [7]; /* Microsoft reserved */ + char ds_attrib; + short ds_time; + short ds_date; + long ds_size; + char ds_nameZ [13]; /* result of the search, asciiz */ +} dosSearchInfo; /* used with DOS functions 4E, 4F */ + + +#ifndef _FFBLK_DEF +#define _FFBLK_DEF +struct ffblk { + char ff_reserved[21]; + char ff_attrib; + unsigned ff_ftime; + unsigned ff_fdate; + long ff_fsize; + char ff_name[13]; +}; +#endif /* _FFBLK_DEF */ + +/* The MSC find_t structure corresponds exactly to the ffblk structure */ +struct find_t { + char reserved[21]; /* Microsoft reserved - do not change */ + char attrib; /* attribute byte for matched file */ + unsigned wr_time; /* time of last write to file */ + unsigned wr_date; /* date of last write to file */ + long size; /* size of file */ + char name[13]; /* asciiz name of matched file */ +}; + +#ifdef __MSC +#define _find_t find_t +#endif + +/* axret values for _hardresume() */ + +#define _HARDERR_IGNORE 0 /* ignore error */ +#define _HARDERR_RETRY 1 /* retry the operation */ +#define _HARDERR_ABORT 2 /* abort program */ +#define _HARDERR_FAIL 3 /* fail the operation */ + +#define SEEK_CUR 1 +#define SEEK_END 2 +#define SEEK_SET 0 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined( _Windows ) +int _Cdecl absread( int __drive, int __nsects, long __lsect, + void _FAR *__buffer ); +int _Cdecl abswrite( int __drive, int __nsects, long __lsect, + void _FAR *__buffer ); +int _Cdecl allocmem( unsigned __size, unsigned _FAR *__segp ); +#endif + +int _CType _FARFUNC bdos( int __dosfun, unsigned __dosdx, unsigned __dosal ); +int _CType bdosptr( int __dosfun, void _FAR *__argument, + unsigned __dosal ); +struct COUNTRY _FAR *_Cdecl country( int __xcode, struct COUNTRY _FAR *__cp); +void _Cdecl ctrlbrk( int _Cdecl( *handler )( void )); + +#if !defined( _Windows ) +void _CType delay( unsigned __milliseconds ); +#endif + +void _Cdecl _FARFUNC disable( void ); +int _Cdecl _FARFUNC dosexterr( struct DOSERROR _FAR *__eblkp ); +long _Cdecl _FARFUNC dostounix( struct date _FAR *__d, struct time _FAR *__t ); + +unsigned _Cdecl _dos_allocmem( unsigned __size, unsigned _FAR *__segp ); +unsigned _Cdecl _dos_close ( int __fd ); +unsigned _Cdecl _dos_commit( int __fd ); +unsigned _Cdecl _dos_creat( const char _FAR *__pathP, unsigned __attr, + int _FAR *__fd ); +unsigned _Cdecl _dos_creatnew( const char _FAR *__pathP, unsigned __attr, + int _FAR *__fd ); +unsigned _Cdecl _dos_findfirst( const char _FAR *__path, + unsigned __attrib, + struct find_t _FAR *__finfo ); +unsigned _Cdecl _dos_findnext( struct find_t _FAR *__finfo ); +unsigned _Cdecl _dos_freemem( unsigned __segx ); +void _Cdecl _dos_getdate( struct dosdate_t _FAR *__datep ); +unsigned _Cdecl _dos_getdiskfree( unsigned __drive, + struct diskfree_t _FAR *__dtable); +void _Cdecl _dos_getdrive( unsigned _FAR *__drive ); +unsigned _Cdecl _dos_getfileattr( const char _FAR *__filename, + unsigned _FAR *__attrib ); +unsigned _Cdecl _dos_getftime( int __fd, unsigned _FAR *__date, + unsigned _FAR *__time ); +void _Cdecl _dos_gettime( struct dostime_t _FAR *__timep ); +void _Cdecl _dos_keep(unsigned char __status, unsigned __size); +unsigned _Cdecl _dos_open( const char _FAR *__pathP, unsigned __oflag, + int _FAR *__fd ); +unsigned _Cdecl _dos_read( int __fd, void far *__buf, unsigned __len, + unsigned _FAR *__nread ); +unsigned _Cdecl _dos_setblock( unsigned __size, unsigned __segx, + unsigned _FAR *__maxp ); +unsigned _Cdecl _dos_setdate( struct dosdate_t _FAR *__datep ); +void _Cdecl _dos_setdrive( unsigned __drive, unsigned _FAR *__ndrives ); +unsigned _Cdecl _dos_setfileattr( const char _FAR *__filename, + unsigned _FAR __attrib); +unsigned _Cdecl _dos_setftime( int __fd, unsigned __date, unsigned __time ); +unsigned _Cdecl _dos_settime( struct dostime_t _FAR *__timep ); +unsigned _Cdecl _dos_write( int __fd, const void far *__buf, unsigned __len, + unsigned _FAR *__nread ); + +void __emit__( unsigned char __byte, ...); +void _Cdecl _FARFUNC enable( void ); + +#if !defined( _Windows ) +int _Cdecl freemem( unsigned __segx ); +#endif + +int _Cdecl getcbrk( void ); +void _CType getdate( struct date _FAR *__datep ); +void _Cdecl getdfree( unsigned char __drive, + struct dfree _FAR *__dtable ); +int _Cdecl _getdrive( void ); +void _Cdecl getfat( unsigned char __drive, + struct fatinfo _FAR *__dtable ); +void _Cdecl getfatd( struct fatinfo _FAR *__dtable ); +unsigned _Cdecl getpsp( void ); +int _Cdecl getswitchar( void ); +void _CType gettime( struct time _FAR *__timep ); +int _Cdecl getverify( void ); + +#if !defined( _Windows ) +#ifdef __cplusplus +void _Cdecl _harderr( void _Cdecl (far *__fptr)( unsigned __deverr, + unsigned __doserr, unsigned far *__hdr) ); +#else +void _Cdecl _harderr( void _Cdecl (far *__fptr)( ) ); +#endif +void _Cdecl _hardresume( int __axret ); +void _Cdecl _hardretn( int __retn ); + +#ifdef __cplusplus +void _CType harderr( int _Cdecl( *__handler )( int __errval, int __ax, + int __bp, int __si) ); +#else +void _CType harderr( int _Cdecl( *__handler )( ) ); +#endif +void _CType hardresume( int __axret ); +void _CType hardretn( int __retn ); +#endif + +#ifndef _PORT_DEFS +unsigned _Cdecl inport ( unsigned __portid ); +unsigned char _Cdecl inportb( unsigned __portid ); +unsigned _Cdecl inpw ( unsigned __portid ); +int _Cdecl inp ( unsigned __portid ); +#endif + +int _Cdecl int86( int __intno, + union REGS _FAR *__inregs, + union REGS _FAR *__outregs ); +int _Cdecl int86x( int __intno, + union REGS _FAR *__inregs, + union REGS _FAR *__outregs, + struct SREGS _FAR *__segregs ); +int _Cdecl intdos( union REGS _FAR *__inregs, + union REGS _FAR *__outregs ); +int _Cdecl intdosx( union REGS _FAR *__inregs, + union REGS _FAR *__outregs, + struct SREGS _FAR *__segregs ); +void _Cdecl intr( int __intno, struct REGPACK _FAR *__preg ); + +#if !defined( _Windows ) +void _Cdecl keep( unsigned char __status, unsigned __size ); +void _Cdecl nosound( void ); +#endif + +#ifndef _PORT_DEFS +void _Cdecl outport ( unsigned __portid, unsigned __value ); +void _Cdecl outportb( unsigned __portid, unsigned char __value ); +unsigned _Cdecl outpw ( unsigned __portid, unsigned __value ); +int _Cdecl outp ( unsigned __portid, int __value ); +#endif + +char _FAR * _Cdecl parsfnm( const char _FAR *__cmdline, + struct fcb _FAR *__fcb, int __opt ); +int _Cdecl peek( unsigned __segment, unsigned __offset ); +char _Cdecl peekb( unsigned __segment, unsigned __offset ); +void _Cdecl poke( unsigned __segment, unsigned __offset, int __value); +void _Cdecl pokeb( unsigned __segment, + unsigned __offset, char __value ); + +#if !defined( _Windows ) +int _Cdecl randbrd( struct fcb _FAR *__fcb, int __rcnt ); +int _Cdecl randbwr( struct fcb _FAR *__fcb, int __rcnt ); +#endif + +void _Cdecl segread( struct SREGS _FAR *__segp ); + +#if !defined( _Windows ) +int _Cdecl setblock( unsigned __segx, unsigned __newsize ); +#endif + +int _Cdecl setcbrk( int __cbrkvalue ); +void _Cdecl setdate( struct date _FAR *__datep ); +void _Cdecl setswitchar( char __ch ); +void _Cdecl settime( struct time _FAR *__timep ); +void _Cdecl setverify( int __value ); + +#if !defined( _Windows ) +void _Cdecl sleep( unsigned __seconds ); +void _Cdecl sound( unsigned __frequency ); +#endif + +void _Cdecl _FARFUNC unixtodos( long __time, struct date _FAR *__d, + struct time _FAR *__t ); +int _CType unlink( const char _FAR *__path ); + + /* These are in-line functions. These prototypes just clean up + some syntax checks and code generation. + */ + +void _Cdecl __cli__( void ); +void _Cdecl __sti__( void ); +void _Cdecl __int__( int __interruptnum ); + +#define disable( ) __emit__( (char )( 0xfa ) ) +#define _disable( ) __emit__( (char )( 0xfa ) ) /* MSC name */ +#define enable( ) __emit__( (char )( 0xfb ) ) +#define _enable( ) __emit__( (char )( 0xfb ) ) /* MSC name */ + +#define geninterrupt( i ) __int__( i ) /* Interrupt instruction */ + +#ifndef _PORT_DEFS +#define _PORT_DEFS + +unsigned char _Cdecl __inportb__ ( unsigned __portid ); +unsigned _Cdecl __inportw__ ( unsigned __portid ); +unsigned char _Cdecl __outportb__( unsigned __portid, unsigned char __value ); +unsigned _Cdecl __outportw__( unsigned __portid, unsigned __value ); + +#define inportb(__portid) __inportb__(__portid) +#define outportb(__portid, __value) ((void) __outportb__(__portid, __value)) +#define inport(__portid) __inportw__(__portid) +#define outport(__portid, __value) ((void) __outportw__(__portid, __value)) + +/* MSC-compatible macros for port I/O */ +#define inp(__portid) __inportb__ (__portid) +#define outp(__portid, __value) __outportb__(__portid, (unsigned char)__value) +#define inpw(__portid) __inportw__ (__portid) +#define outpw(__portid, __value) __outportw__(__portid, __value) + +#endif /* _PORT_DEFS */ + +#if !__STDC__ + +extern unsigned _Cdecl _ovrbuffer; +int cdecl far _OvrInitEms( unsigned __emsHandle, unsigned __emsFirst, + unsigned __emsPages ); +int cdecl far _OvrInitExt( unsigned long __extStart, + unsigned long __extLength ); + +char far *cdecl getdta( void ); +void cdecl setdta( char far *__dta ); + +#define MK_FP( seg,ofs )( (void _seg * )( seg ) +( void near * )( ofs )) +#define FP_SEG( fp )( (unsigned )( void _seg * )( void far * )( fp )) +#define FP_OFF( fp )( (unsigned )( fp )) + +#ifdef __cplusplus +void _Cdecl _chain_intr ( void interrupt (far *__target)( ... )); +void interrupt( far * _Cdecl _dos_getvect( unsigned __interruptno ))( ... ); +void interrupt( far * _CType getvect( int __interruptno ))( ... ); +void _Cdecl _dos_setvect( unsigned __interruptno, + void interrupt( far *__isr )( ... )); +void _CType setvect( int __interruptno, + void interrupt( far *__isr )( ... )); +int inline _Cdecl peek( unsigned __segment, unsigned __offset ) + { return( *( (int far* )MK_FP( __segment, __offset )) ); } +char inline _Cdecl peekb( unsigned __segment, unsigned __offset ) + { return( *( (char far* )MK_FP( __segment, __offset )) ); } +void inline _Cdecl poke( unsigned __segment, unsigned __offset, int __value ) + {( *( (int far* )MK_FP( __segment, __offset )) = __value ); } +void inline _Cdecl pokeb( unsigned __segment, unsigned __offset, char __value ) + {( *( (char far* )MK_FP( __segment, __offset )) = __value ); } +#else +void _Cdecl _chain_intr ( void interrupt (far *__target)( )); +void interrupt( far * _Cdecl _dos_getvect( unsigned __interruptno ))( ); +void interrupt( far * _CType getvect( int __interruptno ))( ); +void _Cdecl _dos_setvect( unsigned __interruptno, + void interrupt( far *__isr )( )); +void _CType setvect( int __interruptno, + void interrupt( far *__isr )( ) ); +#define peek( a,b )( *( (int far* )MK_FP( (a ),( b )) )) +#define peekb( a,b )( *( (char far* )MK_FP( (a ),( b )) )) +#define poke( a,b,c )( *( (int far* )MK_FP( (a ),( b )) ) =( int )( c )) +#define pokeb( a,b,c )( *( (char far* )MK_FP( (a ),( b )) ) =( char )( c )) +#endif /* __cplusplus */ + +#endif /* !__STDC__ */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __DOS_H */ + + \ No newline at end of file diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/MEM.H b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/MEM.H new file mode 100644 index 0000000..d09b551 --- /dev/null +++ b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/MEM.H @@ -0,0 +1,91 @@ +/* mem.h + + Memory manipulation functions + + Copyright (c) 1987, 1992 by Borland International + All Rights Reserved. +*/ + +#if !defined(__MEM_H) +#define __MEM_H + +#if !defined(___DEFS_H) +#include <_defs.h> +#endif + +#ifndef NULL +#include <_null.h> +#endif + +#ifndef _STDDEF +#define _STDDEF +#ifndef _PTRDIFF_T +#define _PTRDIFF_T +#if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) +typedef long ptrdiff_t; +#else +typedef int ptrdiff_t; +#endif +#endif +#ifndef _SIZE_T +#define _SIZE_T +typedef unsigned size_t; +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif +void _FAR * _FARFUNC _Cdecl memccpy(void _FAR *__dest, const void _FAR *__src, + int __c, size_t __n); +void _FAR * _FARFUNC _Cdecl memchr(const void _FAR *__s, int __c, size_t __n); +int _FARFUNC _Cdecl memcmp(const void _FAR *__s1, const void _FAR *__s2, + size_t __n); +void _FAR * _FARFUNC _Cdecl memcpy(void _FAR *__dest, const void _FAR *__src, + size_t __n); +int _FARFUNC _Cdecl memicmp(const void _FAR *__s1, const void _FAR *__s2, + size_t __n); +void _FAR * _CType _FARFUNC memmove(void _FAR *__dest, const void _FAR *__src, + size_t __n); +void _FAR * _CType _FARFUNC memset(void _FAR *__s, int __c, size_t __n); +void _FARFUNC _Cdecl movedata(unsigned __srcseg, unsigned __srcoff, + unsigned __dstseg,unsigned __dstoff, size_t __n); +void _FARFUNC _Cdecl movmem(const void _FAR *__src, void _FAR *__dest, + unsigned __length); +void _FARFUNC _Cdecl setmem(void _FAR *__dest,unsigned __length, char __value); + +#if !__STDC__ +void far * _FARCALL cdecl _fmemccpy(void far *__dest, const void far *__src, + int __c, size_t __n); +void far * _FARCALL cdecl _fmemchr(const void far *__s, int __c, size_t __n); +int _FARCALL cdecl _fmemcmp(const void far *__s1, const void far *__s2, + size_t __n); +void far * _FARCALL cdecl _fmemcpy(void far *__dest, const void far *__src, + size_t __n); +int _FARCALL cdecl _fmemicmp(const void far *__s1, const void far *__s2, + size_t __n); +void far * _FARCALL cdecl _fmemmove(void far *__dest, const void far *__src, + size_t __n); +void far * _FARCALL cdecl _fmemset(void far *__s, int __c, size_t __n); +void _FARCALL cdecl _fmovmem(const void far *__src, void far *__dest, + unsigned __length); +void _FARCALL cdecl _fsetmem(void far *__dest, unsigned __length, + char __value); +#endif + +#if !defined(__STRING_H) +/* Intrinsic functions */ + +void _FAR * _Cdecl _FARFUNC __memchr__ (const void _FAR *__s, int __c, size_t __n); +int _Cdecl _FARFUNC __memcmp__(const void _FAR *__s1, + const void _FAR *__s2, size_t __n); +void _FAR * _Cdecl _FARFUNC __memcpy__(void _FAR *__dest, const void _FAR *__src, + size_t __n); +void _FAR * _CType _FARFUNC __memset__(void _FAR *__s, int __c, size_t __n); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* __MEM_H */ + diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/STDARG.H b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/STDARG.H new file mode 100644 index 0000000..4f27929 --- /dev/null +++ b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/STDARG.H @@ -0,0 +1,38 @@ +/* stdarg.h + + Definitions for accessing parameters in functions that accept + a variable number of arguments. + + Copyright (c) 1987, 1992 by Borland International + All Rights Reserved. +*/ + +#ifndef __STDARG_H +#define __STDARG_H + +#ifdef __VARARGS_H +#error Can't include both STDARG.H and VARARGS.H +#endif + +#if !defined(___DEFS_H) +#include <_defs.h> +#endif + +typedef void _FAR *va_list; + +#define __size(x) ((sizeof(x)+sizeof(int)-1) & ~(sizeof(int)-1)) + +#if defined(__cplusplus) && !defined(__STDC__) +#define va_start(ap, parmN) (ap = ...) +#else +#define va_start(ap, parmN) ((void)((ap) = (va_list)((char _FAR *)(&parmN)+__size(parmN)))) +#endif + +#define va_arg(ap, type) (*(type _FAR *)(((*(char _FAR *_FAR *)&(ap))+=__size(type))-(__size(type)))) +#define va_end(ap) ((void)0) + +#if !__STDC__ +#define _va_ptr (...) +#endif + +#endif diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/STDIO.H b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/STDIO.H new file mode 100644 index 0000000..032b328 --- /dev/null +++ b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/STDIO.H @@ -0,0 +1,248 @@ +/* stdio.h + + Definitions for stream input/output. + + Copyright (c) 1987, 1992 by Borland International + All Rights Reserved. +*/ + +#ifndef __STDIO_H +#define __STDIO_H + +#if !defined(___DEFS_H) +#include <_defs.h> +#endif + +#if !defined(___NFILE_H) +#include <_nfile.h> +#endif + +#ifndef NULL +#include <_null.h> +#endif + +#ifndef _SIZE_T +#define _SIZE_T +typedef unsigned size_t; +#endif + +/* Definition of the file position type +*/ +typedef long fpos_t; + + +/* Definition of the control structure for streams +*/ +typedef struct { + int level; /* fill/empty level of buffer */ + unsigned flags; /* File status flags */ + char fd; /* File descriptor */ + unsigned char hold; /* Ungetc char if no buffer */ + int bsize; /* Buffer size */ + unsigned char _FAR *buffer; /* Data transfer buffer */ + unsigned char _FAR *curp; /* Current active pointer */ + unsigned istemp; /* Temporary file indicator */ + short token; /* Used for validity checking */ +} FILE; /* This is the FILE object */ + +/* Bufferisation type to be used as 3rd argument for "setvbuf" function +*/ +#define _IOFBF 0 +#define _IOLBF 1 +#define _IONBF 2 + +/* "flags" bits definitions +*/ +#define _F_RDWR 0x0003 /* Read/write flag */ +#define _F_READ 0x0001 /* Read only file */ +#define _F_WRIT 0x0002 /* Write only file */ +#define _F_BUF 0x0004 /* Malloc'ed Buffer data */ +#define _F_LBUF 0x0008 /* line-buffered file */ +#define _F_ERR 0x0010 /* Error indicator */ +#define _F_EOF 0x0020 /* EOF indicator */ +#define _F_BIN 0x0040 /* Binary file indicator */ +#define _F_IN 0x0080 /* Data is incoming */ +#define _F_OUT 0x0100 /* Data is outgoing */ +#define _F_TERM 0x0200 /* File is a terminal */ + +/* End-of-file constant definition +*/ +#define EOF (-1) /* End of file indicator */ + +/* Number of files that can be open simultaneously +*/ +#if __STDC__ +#define FOPEN_MAX (_NFILE_ - 2) /* (_NFILE_ - stdaux & stdprn) */ +#else +#define FOPEN_MAX (_NFILE_) /* Able to have 20 files */ +#define SYS_OPEN (_NFILE_) +#endif + +#define FILENAME_MAX 80 + +/* Default buffer size use by "setbuf" function +*/ +#define BUFSIZ 512 /* Buffer size for stdio */ + +/* Size of an arry large enough to hold a temporary file name string +*/ +#define L_ctermid 5 /* CON: plus null byte */ +#define P_tmpdir "" /* temporary directory */ +#define L_tmpnam 13 /* tmpnam buffer size */ + +/* Constants to be used as 3rd argument for "fseek" function +*/ +#define SEEK_CUR 1 +#define SEEK_END 2 +#define SEEK_SET 0 + +/* Number of unique file names that shall be generated by "tmpnam" function +*/ +#define TMP_MAX 0xFFFF + +/* Standard I/O predefined streams +*/ + +#if !defined( _RTLDLL ) +extern FILE _Cdecl _streams[]; +extern unsigned _Cdecl _nfile; + +#define stdin (&_streams[0]) +#define stdout (&_streams[1]) +#define stderr (&_streams[2]) + +#if !__STDC__ +#define stdaux (&_streams[3]) +#define stdprn (&_streams[4]) +#endif + +#else + +#ifdef __cplusplus +extern "C" { +#endif +FILE far * far __getStream(int); +#ifdef __cplusplus +} +#endif + +#define stdin __getStream(0) +#define stdout __getStream(1) +#define stderr __getStream(2) +#define stdaux __getStream(3) +#define stdprn __getStream(4) + +#endif + +#ifdef __cplusplus +extern "C" { +#endif +void _Cdecl clearerr(FILE _FAR *__stream); +int _Cdecl _FARFUNC fclose(FILE _FAR *__stream); +int _Cdecl _FARFUNC fflush(FILE _FAR *__stream); +int _Cdecl _FARFUNC fgetc(FILE _FAR *__stream); +int _Cdecl fgetpos(FILE _FAR *__stream, fpos_t _FAR *__pos); +char _FAR *_Cdecl _FARFUNC fgets(char _FAR *__s, int __n, FILE _FAR *__stream); +FILE _FAR *_Cdecl _FARFUNC fopen(const char _FAR *__path, const char _FAR *__mode); +int _Cdecl _FARFUNC fprintf(FILE _FAR *__stream, const char _FAR *__format, ...); +int _Cdecl _FARFUNC fputc(int __c, FILE _FAR *__stream); +int _Cdecl _FARFUNC fputs(const char _FAR *__s, FILE _FAR *__stream); +size_t _Cdecl _FARFUNC fread(void _FAR *__ptr, size_t __size, size_t __n, + FILE _FAR *__stream); +FILE _FAR *_Cdecl _FARFUNC freopen(const char _FAR *__path, const char _FAR *__mode, + FILE _FAR *__stream); +int _Cdecl _FARFUNC fscanf(FILE _FAR *__stream, const char _FAR *__format, ...); +int _Cdecl _FARFUNC fseek(FILE _FAR *__stream, long __offset, int __whence); +int _Cdecl fsetpos(FILE _FAR *__stream, const fpos_t _FAR *__pos); +long _Cdecl _FARFUNC ftell(FILE _FAR *__stream); +size_t _Cdecl _FARFUNC fwrite(const void _FAR *__ptr, size_t __size, size_t __n, + FILE _FAR *__stream); +char _FAR *_Cdecl gets(char _FAR *__s); +void _Cdecl perror(const char _FAR *__s); +int _Cdecl printf(const char _FAR *__format, ...); +int _Cdecl puts(const char _FAR *__s); +int _CType remove(const char _FAR *__path); +int _CType _FARFUNC rename(const char _FAR *__oldname,const char _FAR *__newname); +void _Cdecl _FARFUNC rewind(FILE _FAR *__stream); +int _Cdecl scanf(const char _FAR *__format, ...); +void _Cdecl setbuf(FILE _FAR *__stream, char _FAR *__buf); +int _Cdecl _FARFUNC setvbuf(FILE _FAR *__stream, char _FAR *__buf, + int __type, size_t __size); +int _Cdecl _FARFUNC sprintf(char _FAR *__buffer, const char _FAR *__format, ...); +int _Cdecl _FARFUNC sscanf(const char _FAR *__buffer, + const char _FAR *__format, ...); +char _FAR *_Cdecl _FARFUNC strerror(int __errnum); +FILE _FAR *_Cdecl _FARFUNC tmpfile(void); +char _FAR *_Cdecl _FARFUNC tmpnam(char _FAR *__s); +int _Cdecl _FARFUNC ungetc(int __c, FILE _FAR *__stream); +int _Cdecl _FARFUNC vfprintf(FILE _FAR *__stream, const char _FAR *__format, + void _FAR *__arglist); +int _Cdecl _FARFUNC vfscanf(FILE _FAR *__stream, const char _FAR *__format, + void _FAR *__arglist); +int _CType vprintf(const char _FAR *__format, void _FAR *__arglist); +int _Cdecl vscanf(const char _FAR *__format, void _FAR *__arglist); +int _Cdecl _FARFUNC vsprintf(char _FAR *__buffer, const char _FAR *__format, + void _FAR *__arglist); +int _Cdecl _FARFUNC vsscanf(const char _FAR *__buffer, const char _FAR *__format, + void _FAR *__arglist); +int _CType unlink(const char _FAR *__path); +int _Cdecl getc(FILE _FAR *__fp); + +int _Cdecl getchar(void); +int _Cdecl putchar(const int __c); + +int _Cdecl putc(const int __c, FILE _FAR *__fp); +int _Cdecl feof(FILE _FAR *__fp); +int _Cdecl ferror(FILE _FAR *__fp); + + +#if !__STDC__ +int _Cdecl _FARFUNC fcloseall(void); +FILE _FAR *_Cdecl _FARFUNC fdopen(int __handle, char _FAR *__type); +int _Cdecl _FARFUNC fgetchar(void); +int _Cdecl _FARFUNC flushall(void); +int _Cdecl _FARFUNC fputchar(int __c); +FILE _FAR * _Cdecl _fsopen (const char _FAR *__path, const char _FAR *__mode, + int __shflag); +int _Cdecl getw(FILE _FAR *__stream); +int _Cdecl putw(int __w, FILE _FAR *__stream); +int _Cdecl rmtmp(void); +char _FAR * _Cdecl _FARFUNC _strerror(const char _FAR *__s); +char _FAR * _Cdecl _FARFUNC tempnam(char _FAR *__dir, char _FAR *__pfx); + +#define fileno(f) ((f)->fd) +#ifdef __MSC +#define _fileno(f) fileno(f) +#endif + +#endif /* !__STDC__ */ + +int _Cdecl _FARFUNC _fgetc(FILE _FAR *__stream); /* used by getc() macro */ +int _Cdecl _FARFUNC _fputc(char __c, FILE _FAR *__stream); /* used by putc() macro */ + +void _Cdecl _InitEasyWin(void); /* Initialization call for Easy Windows */ + +#ifdef __cplusplus +} +#endif + +/* The following macros provide for common functions */ + +#define ferror(f) ((f)->flags & _F_ERR) +#define feof(f) ((f)->flags & _F_EOF) + +#define getc(f) \ + ((--((f)->level) >= 0) ? (unsigned char)(*(f)->curp++) : \ + _fgetc (f)) + +#define putc(c,f) \ + ((++((f)->level) < 0) ? (unsigned char)(*(f)->curp++=(c)) : \ + _fputc ((c),f)) + +#define getchar() getc(stdin) +#define putchar(c) putc((c), stdout) + +#define ungetc(c,f) ungetc((c),f) /* traditionally a macro */ + +#endif + diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/_DEFS.H b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/_DEFS.H new file mode 100644 index 0000000..4806204 --- /dev/null +++ b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/_DEFS.H @@ -0,0 +1,104 @@ +/* _defs.h + + Common definitions for pointer size and calling conventions. + + Copyright (c) 1991, 1992 by Borland International + All Rights Reserved. +*/ + +#if !defined(___DEFS_H) +#define ___DEFS_H + +#if __STDC__ +# define _Cdecl +#else +# define _Cdecl cdecl +#endif + +#ifndef __PAS__ +# define _CType _Cdecl +#else +# define _CType pascal +#endif + +#ifdef __MSC +# define _emit db +# define __far _far +# define __near _near +# define __cdecl _cdecl +# define __pascal _pascal +# define __export _export +# ifdef __SMALL__ +# define _M_I86SM +# endif +# ifdef __COMPACT__ +# define _M_I86CM +# endif +# ifdef __MEDIUM__ +# define _M_I86MM +# endif +# ifdef __LARGE__ +# define _M_I86LM +# endif +# ifndef _Windows +# define _DOS +# else +# define _WINDOWS +# endif +#endif + +#if defined(__STDC__) +# define _FAR +# define _FARFUNC +# define _CLASSTYPE +#else +# if defined(_BUILDRTLDLL) +# define _FARFUNC _export +# elif defined(_RTLDLL) +# define _FARFUNC far +# else +# define _FARFUNC +# endif +# if defined(__DLL__) +# if defined(_RTLDLL) || defined(_CLASSDLL) +# define _CLASSTYPE _export +# else +# define _CLASSTYPE far +# endif +# define _FAR far +# elif defined(_RTLDLL) || defined(_CLASSDLL) +# define _CLASSTYPE huge +# define _FAR far +# else +# define _FAR +# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__) +# define _CLASSTYPE near +# elif defined(__COMPACT__) || defined(__LARGE__) +# define _CLASSTYPE far +# else +# define _CLASSTYPE huge +# endif +# endif +#endif /* __STDC__ */ + +#if defined(_BUILDRTLDLL) +# define _FARCALL _export +#else +# define _FARCALL far +#endif + +#if defined( __cplusplus ) +# define _PTRDEF(name) typedef name _FAR * P##name; +# define _REFDEF(name) typedef name _FAR & R##name; +# define _REFPTRDEF(name) typedef name _FAR * _FAR & RP##name; +# define _PTRCONSTDEF(name) typedef const name _FAR * PC##name; +# define _REFCONSTDEF(name) typedef const name _FAR & RC##name; +# define _CLASSDEF(name) class _CLASSTYPE name; \ + _PTRDEF(name) \ + _REFDEF(name) \ + _REFPTRDEF(name) \ + _PTRCONSTDEF(name) \ + _REFCONSTDEF(name) +#endif + +#endif /* ___DEFS_H */ diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/_NFILE.H b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/_NFILE.H new file mode 100644 index 0000000..b7411a9 --- /dev/null +++ b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/_NFILE.H @@ -0,0 +1,14 @@ +/* _nfile.h + + Maximum number of open files + + Copyright (c) 1991, 1992 by Borland International + All Rights Reserved. +*/ + +#ifndef ___NFILE_H +#define ___NFILE_H + +#define _NFILE_ 20 + +#endif diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/_NULL.H b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/_NULL.H new file mode 100644 index 0000000..221ec2f --- /dev/null +++ b/XTMax/Drivers/Driver_Build_Tools/BCC31/INCLUDE/_NULL.H @@ -0,0 +1,15 @@ +/* _null.h + + Definition of NULL. + + Copyright (c) 1987, 1992 by Borland International + All Rights Reserved. +*/ + +#ifndef NULL +# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__) +# define NULL 0 +# else +# define NULL 0L +# endif +#endif diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/MAKE.EXE b/XTMax/Drivers/Driver_Build_Tools/BCC31/MAKE.EXE new file mode 100644 index 0000000..9918ac8 Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/BCC31/MAKE.EXE differ diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/TASM.EXE b/XTMax/Drivers/Driver_Build_Tools/BCC31/TASM.EXE new file mode 100644 index 0000000..f3867a6 Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/BCC31/TASM.EXE differ diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/TLINK.CFG b/XTMax/Drivers/Driver_Build_Tools/BCC31/TLINK.CFG new file mode 100644 index 0000000..02377ae --- /dev/null +++ b/XTMax/Drivers/Driver_Build_Tools/BCC31/TLINK.CFG @@ -0,0 +1 @@ +-LD:\LIB diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/TLINK.EXE b/XTMax/Drivers/Driver_Build_Tools/BCC31/TLINK.EXE new file mode 100644 index 0000000..b46896d Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/BCC31/TLINK.EXE differ diff --git a/XTMax/Drivers/Driver_Build_Tools/BCC31/TURBOC.CFG b/XTMax/Drivers/Driver_Build_Tools/BCC31/TURBOC.CFG new file mode 100644 index 0000000..245f00a --- /dev/null +++ b/XTMax/Drivers/Driver_Build_Tools/BCC31/TURBOC.CFG @@ -0,0 +1,2 @@ +-ID:\INCLUDE +-LD:\LIB diff --git a/XTMax/Drivers/Driver_Build_Tools/DOSBox/DOSBox.exe b/XTMax/Drivers/Driver_Build_Tools/DOSBox/DOSBox.exe new file mode 100644 index 0000000..59adb23 Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/DOSBox/DOSBox.exe differ diff --git a/XTMax/Drivers/Driver_Build_Tools/DOSBox/SDL.dll b/XTMax/Drivers/Driver_Build_Tools/DOSBox/SDL.dll new file mode 100644 index 0000000..37d3151 Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/DOSBox/SDL.dll differ diff --git a/XTMax/Drivers/Driver_Build_Tools/DOSBox/SDL_net.dll b/XTMax/Drivers/Driver_Build_Tools/DOSBox/SDL_net.dll new file mode 100644 index 0000000..924e654 Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/DOSBox/SDL_net.dll differ diff --git a/XTMax/Drivers/Driver_Build_Tools/TASM2/GREP.COM b/XTMax/Drivers/Driver_Build_Tools/TASM2/GREP.COM new file mode 100644 index 0000000..62d1b42 Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/TASM2/GREP.COM differ diff --git a/XTMax/Drivers/Driver_Build_Tools/TASM2/MAKE.EXE b/XTMax/Drivers/Driver_Build_Tools/TASM2/MAKE.EXE new file mode 100644 index 0000000..c2028f7 Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/TASM2/MAKE.EXE differ diff --git a/XTMax/Drivers/Driver_Build_Tools/TASM2/OBJXREF.COM b/XTMax/Drivers/Driver_Build_Tools/TASM2/OBJXREF.COM new file mode 100644 index 0000000..8b3f28a Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/TASM2/OBJXREF.COM differ diff --git a/XTMax/Drivers/Driver_Build_Tools/TASM2/TASM.EXE b/XTMax/Drivers/Driver_Build_Tools/TASM2/TASM.EXE new file mode 100644 index 0000000..183f6d8 Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/TASM2/TASM.EXE differ diff --git a/XTMax/Drivers/Driver_Build_Tools/TASM2/TCREF.EXE b/XTMax/Drivers/Driver_Build_Tools/TASM2/TCREF.EXE new file mode 100644 index 0000000..de9e655 Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/TASM2/TCREF.EXE differ diff --git a/XTMax/Drivers/Driver_Build_Tools/TASM2/TLIB.EXE b/XTMax/Drivers/Driver_Build_Tools/TASM2/TLIB.EXE new file mode 100644 index 0000000..28b905a Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/TASM2/TLIB.EXE differ diff --git a/XTMax/Drivers/Driver_Build_Tools/TASM2/TLINK.EXE b/XTMax/Drivers/Driver_Build_Tools/TASM2/TLINK.EXE new file mode 100644 index 0000000..33eed06 Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/TASM2/TLINK.EXE differ diff --git a/XTMax/Drivers/Driver_Build_Tools/TASM2/TOUCH.COM b/XTMax/Drivers/Driver_Build_Tools/TASM2/TOUCH.COM new file mode 100644 index 0000000..de1a2f5 Binary files /dev/null and b/XTMax/Drivers/Driver_Build_Tools/TASM2/TOUCH.COM differ diff --git a/XTMax/Drivers/LTEMM/.gitignore b/XTMax/Drivers/LTEMM/.gitignore new file mode 100644 index 0000000..d67c2f9 --- /dev/null +++ b/XTMax/Drivers/LTEMM/.gitignore @@ -0,0 +1,3 @@ +*.o +*.map +log.txt diff --git a/XTMax/Drivers/LTEMM/.vscode/tasks.json b/XTMax/Drivers/LTEMM/.vscode/tasks.json new file mode 100644 index 0000000..b9c2cd2 --- /dev/null +++ b/XTMax/Drivers/LTEMM/.vscode/tasks.json @@ -0,0 +1,20 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Build in DOSBox", + "type": "shell", + "command": "..\\Driver_Build_Tools\\DOSBox\\DOSBox.exe -conf Build.conf", + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [], + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} diff --git a/XTMax/Drivers/LTEMM/Build.conf b/XTMax/Drivers/LTEMM/Build.conf new file mode 100644 index 0000000..7494c04 --- /dev/null +++ b/XTMax/Drivers/LTEMM/Build.conf @@ -0,0 +1,15 @@ +[autoexec] +@ECHO OFF +CLS +MOUNT C . +MOUNT D ..\Driver_Build_Tools\TASM2 +SET PATH=D:\ +C: +MAKE > LOG.TXT +IF ERRORLEVEL 1 GOTO :ERROR +EXIT +:ERROR +TYPE LOG.TXT +ECHO Log saved to LOG.TXT +PAUSE +EXIT diff --git a/XTMax/Drivers/LTEMM/LTEMM.ASM b/XTMax/Drivers/LTEMM/LTEMM.ASM new file mode 100644 index 0000000..2fb64e7 --- /dev/null +++ b/XTMax/Drivers/LTEMM/LTEMM.ASM @@ -0,0 +1,3600 @@ + PAGE 90,132 + NAME LTEMM + include LTEMM.MAC ; macros + include LTEMM.INC ; structures +; +;************************************************************************ +;* * +;* EMS 4.0 Driver for Lo-tech 2MB EMS Board, rev.01, Mar-14 * +;* * +;* http://www.lo-tech.co.uk/wiki/2MB-EMS-Board * +;* http://www.lo-tech.co.uk/wiki/LTEMM.EXE * +;* * +;* This code is TASM source. * +;* * +;* Based on original works Copyright (c) 1988, Alex Tsourikov. * +;* All rights reserved. * +;* * +;* Original source kindly provided subject to the BSD 3-Clause * +;* License: http://opensource.org/licenses/BSD-3-Clause * +;* * +;* This software, as modified, is provided subject to the terms * +;* of use at: * +;* * +;* http://www.lo-tech.co.uk/wiki/lo-tech.co.uk:General_disclaimer * +;* * +;* No charge has been made for this software. * +;* * +;************************************************************************ + +code SEGMENT + ASSUME CS:code + + ORG 0000H + + ; DEVICE header block +emmdrv DW -1,-1 ;Link to next device (none) + DW 8000H + DW OFFSET emmstat + DW OFFSET emmint + DB 'EMMXXXX0' ; required - this is how apps + ; detect EMS driver is present + +ptrsav LABEL DWORD +parofs DW 0 +parseg DW 0 + +;-------------------------------------------------------------------- +; EMM driver work data area +;-------------------------------------------------------------------- +emsio LABEL WORD +ems_io DW 260h ;Default EMS i/o port address +emm_flag db 0 ;EMM driver install status +backup_count DB 0 ;mapping data backup count +OSE_flag DW 0 ;OS/E function enable flag +OSE_fast DW 0 ;OS/E fast access flag +access_key_h DW 0 ;OS/E access key high +access_key_l DW 0 ;OS/E access key low +alter_map LABEL DWORD +alter_map_off DW 0 +alter_map_seg DW 0 +page_ptr DW alloc_page ;allocate page buffer pointer. +page_frame_seg DW 0E000h ;Default physical page frame address +total_pages DW PAGE_MAX ;total logical page count +un_alloc_pages DW PAGE_MAX ;unallocate logical page count +handle_count DW 0 ;EMM handle used count +jump_addr DW 0 ;EMM function jump address data area +; +; physical page status data area +; +map_table LABEL phys_page_struct + DB SIZE phys_page_struct * PHYS_PAGES DUP (-1) +; +; handle status flag buffer pointers (handle) +; +alloc_page_count LABEL BYTE +; +; allocate page count buffer pointers (handle) +; +handle_flag equ $+1 + dw HANDLE_CNT DUP(0) +; +; mapping data backup buffer pointers (handle) +; +back_address LABEL WORD + dw HANDLE_CNT DUP(0) +; +; allocate pages buffer pointers (handle) +; +page_address LABEL WORD + dw HANDLE_CNT DUP(0) +; +; mapping data backup area +; +backup_map LABEL WORD + db SIZE phys_page_struct * PHYS_PAGES * BACK_MAX DUP(-1) +; +; backup area status flags +; +backup_flags LABEL BYTE + db BACK_MAX DUP(0) +; +; allocate data area +; +alloc_page LABEL WORD + dw PAGE_MAX DUP(-1) +; +; logical page kanri data +; 55AAH:not used , 0 - 254:used , FFFFH:bad or non +; +log_page LABEL WORD + dw PAGE_MAX DUP(-1) +; +;==================================================================== +; +; Define offsets for io data packet +; +iodat STRUC + cmdlen DB ? ;LENGTH OF THIS COMMAND + unit DB ? ;SUB UNIT SPECIFIER + cmd DB ? ;COMMAND CODE + status DW ? ;STATUS + DB 8 DUP (?) + media DB ? ;MEDIA DESCRIPTOR + trans DD ? ;TRANSFER ADDRESS + count DW ? ;COUNT OF BLOCKS OR CHARACTERS + start DW ? ;FIRST BLOCK TO TRANSFER +iodat ENDS + +; +; Define offsets for io data packet 2 +; +iodat2 STRUC + DB 13 DUP (?) + DB ? + brkoff DW ? ;BREAK ADDRESS (OFFSET) + brkseg DW ? ;BREAK ADDRESS (SEGMENT) +iodat2 ENDS + +; +; Simplistic Strategy routine for non-multi-Tasking system. +; +; Currently just saves I/O packet pointers in PTRSAV for +; later processing by the individual interrupt routines. +; +emmstat PROC FAR + MOV CS:parofs,BX ; + MOV CS:parseg,ES ; + RET +emmstat ENDP + +; +; Common program for handling the simplistic I/O packet +; processing scheme in MSDOS +; +emmint PROC FAR + PUSH AX BX DS + LDS BX,CS:ptrsav ;Retrieve pointer to I/O Packet. + MOV AL,[BX].cmd ;Retrieve Command type. (1 => 16) + CMP AL,10h ;Verify that not more than 16 commands. + JA cmderr ;Ah, well, error out. + OR AL,AL ;init. command? + JNZ emmchk ;check EMS flag. + JMP emminit ;EMS Driver initial. +cmderr: + MOV AL,3 ;Set unknown command error #. +err_exit: ; + MOV AH,10000001B ;Set error and done bits. + JMP short exit1 ;Quick way out. +; +; EMM driver install check routine +; +emmchk: + CMP CS:emm_flag,1 ;EMM install flag on? + JNZ err_exit ;no +exit: + MOV AH,00000001B ;Set done bit for MSDOS. +exit1: + LDS BX,CS:ptrsav ;Retrieve pointer to I/O Packet. + MOV [BX].status,AX ;Save operation compete and status. + POP DS BX AX + RET +emmint ENDP + +;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +;-------------------------------------------------------------------- +; int 67H EMM driver main routine +;-------------------------------------------------------------------- +int67 PROC FAR + CLI + SUB SP,EMMWORK + PUSH DS ES BP DI SI DX CX BX + MOV BP,SP + CLD + PUSH CS + POP DS + + ASSUME DS:code + + CMP AH,40H ; function code check + JC err84 ; FUNCTION 1 - 30 ? +f_max equ $+2 + CMP AH,5EH + JNC err84 + PUSH BX + MOV jump_addr,AX + XCHG AH,AL + AND AL,0BFH + CBW + SHL AX,1 + MOV BX,AX + MOV AX,func_table[BX] + XCHG AX,jump_addr + POP BX + JMP jump_addr ;---- jump to functions ----- +noerr: ;normal return point. + XOR AH,AH +err_ret: ;error return point. + POP BX CX DX SI DI BP ES DS + ADD SP,EMMWORK + IRET +int67 ENDP + +;-------------------------------------------------------------------- +; error status set routine +;-------------------------------------------------------------------- + +;The manager detected a malfunction in the EMM software. +err80: + MOV AH,80H + JMP err_ret + +;The manager detected a malfunction in the expanded memory hardware. +;err81: +; MOV AH,81H +; JMP err_ret + +;The EMM couldn't find the EMM handle your program specified. +err83: + MOV AH,83H + JMP err_ret + +;The function code passed to the EMM is not defined. +err84: + MOV AH,84H + JMP err_ret + +;All EMM handles are being used. +err85: + MOV AH,85H + JMP err_ret + +;The EMM detected a "save" or "restore" page mapping context error. +err86: + MOV AH,86H + JMP err_ret + +;There aren't enough expanded memory pages to satisfy your program's request. +err87: + MOV AH,87H + JMP err_ret + +;There aren't enough unallocated pages to satisfy your program's request. +err88: + MOV AH,88H + JMP err_ret + +;Can't allocate zero (0) pages. +err89: + MOV AH,89H + JMP err_ret + +;The logical page is out of the range of logical pages which are allocated to +;the EMM handle. +err8a: + MOV AH,8AH + JMP err_ret + +;The physical page to which the logical page is mapped is out of the range of +;physical pages. +err8b: + MOV AH,8BH + JMP err_ret + +;The page mapping hardware state save area is full. +err8c: + MOV AH,8CH + JMP err_ret + +;The page mapping hardware state save area already has a state associated with +;the EMM handle. +err8d: + MOV AH,8DH + JMP err_ret + +;The page mapping hardware state save area doesn't have a state associated with +;the EMM handle. +err8e: + MOV AH,8EH + JMP err_ret + +;The subfunction parameter passed to the function isn't defined. +err8f: + MOV AH,8FH + JMP err_ret + +;The attrbute type is undefined. +err90: + MOV AH,90H + JMP err_ret + +;The system configuration does not support non_volatility. +err91: + MOV AH,91H + JMP err_ret + +;The source and destination expanded memory region have the same handle and +;overlap. (move) +err92: + MOV AH,92H + JMP err_ret + +;The length of the specified source or destination expanded memory region +;exceeds the length of the expanded memory region allocated to the specified +;source or destination handle. +err93: + MOV AH,93H + JMP err_ret + +;The conventional memory region and expanded memory region overlap. +err94: + MOV AH,94H + JMP err_ret + +;The offset within the logical page exceeds the length of the logical page. +err95: + MOV AH,95H + JMP err_ret + +;Region length exceeds 1M_byte limit. +err96: + MOV AH,96H + JMP err_ret + +;The source and destination expanded memory region have the same handle and +;overlap. (exchanged) +err97: + MOV AH,97H + JMP err_ret + +;The memory source and destination type are undefined/not supported. +err98: + MOV AH,98H + JMP err_ret + +;Alternate map register serts are supported, but the alternate map register set +;specified is not support. +err9a: + MOV AH,9AH + JMP err_ret + +;Alternate map/DMA register sets are supported. However, all alternate map/DMA +;register sets are currently allocated. +err9b: + MOV AH,9BH + JMP err_ret + +;Alternate map/DMA register sets are not supported, and the alternate map/DMA +;register set specified is not zero. +err9c: + MOV AH,9CH + JMP err_ret + +;Alternate map register serts are supported, but the alternate map register set +;specified is not defined, not allocated, or is the currently allocated map +;register set. +err9d: + MOV AH,9DH + JMP err_ret + +;Dedicated DMA channels are not supported. +err9e: + MOV AH,9EH + JMP err_ret + +;Dedicated DMA channels are not supported. But the DMA channel specified is not +;supported. +err9f: + MOV AH,9FH + JMP err_ret + +;No corresponding handle value could be found for the handle name specified. +erra0: + MOV AH,0A0H + JMP err_ret + +;A handle with this name already exists. +erra1: + MOV AH,0A1H + JMP err_ret + +;An attempt was made to "wrap around" the 1M_byte address space during the +;move/exchange. +erra2: + MOV AH,0A2H + JMP err_ret + +;The contents of the data structure passed to the function have either been +;corrupted or are meaningless. +erra3: + MOV AH,0A3H + JMP err_ret + +;The operating system has denied access to the this function. +erra4: + MOV AH,0A4H + JMP err_ret + +;-------------------------------------------------------------------- +; EMM driver function jump table +; (40H - 5DH) +;-------------------------------------------------------------------- +func_table LABEL WORD + DW OFFSET noerr + DW OFFSET func2 + DW OFFSET func3 + DW OFFSET func4 + DW OFFSET func5 + DW OFFSET func6 + DW OFFSET func7 + DW OFFSET func8 + DW OFFSET func9 + DW OFFSET err84 + DW OFFSET err84 + DW OFFSET func12 + DW OFFSET func13 + DW OFFSET func14 + DW OFFSET func15 + DW OFFSET func16 + DW OFFSET func17 + DW OFFSET func18 + DW OFFSET func19 + DW OFFSET func20 + DW OFFSET func21 + DW OFFSET func22 + DW OFFSET func23 + DW OFFSET func24 + DW OFFSET func25 + DW OFFSET func26 + DW OFFSET func27 + DW OFFSET func28 + DW OFFSET func29 + DW OFFSET func30 + +;======================================================================== + +;-------------------------------------------------------------------- +; Set physical page map. +; output +; CF = 0 : OK +; CF = 1 : NG +;-------------------------------------------------------------------- +set_pages_map PROC NEAR + PUSH AX CX DX DI + MOV DI,OFFSET map_table + MOV CX,PHYS_PAGES +set_pages_map2: + MOV DX,CS:[DI].phys_page_port + MOV AL,CS:[DI].log_page_data + OUT DX,AL ;mapping physical pages... + ADD DI,SIZE phys_page_struct + LOOP set_pages_map2 + POP DI DX CX AX + RET +set_pages_map ENDP +;-------------------------------------------------------------------- +; Reset physical page. +; input +; AL : physical page no. +;-------------------------------------------------------------------- +reset_phys_page PROC NEAR + PUSH AX CX DX DI + cbw + MOV DI,OFFSET map_table + MOV CL,SIZE phys_page_struct + MUL CL + ADD DI,AX + MOV DX,CS:[DI].phys_page_port + MOV AL,DIS_EMS + OUT DX,AL + MOV CS:[DI].emm_handle2,UNMAP + MOV CS:[DI].log_page_data,AL;logical page no. + POP DI DX CX AX + RET +reset_phys_page ENDP +;-------------------------------------------------------------------- +; Check mapping data. +; input +; ES:DI : pointer to mapping data +; output +; CF = 0 : OK +; CF = 1 : NG +;-------------------------------------------------------------------- +check_map_data PROC NEAR + PUSH AX CX SI DI + MOV SI,OFFSET map_table + MOV CX,PHYS_PAGES +check_map_data3: + MOV AX,ES:[DI].phys_page_port + CMP AX,CS:[SI].phys_page_port + jne check_map_data1 + MOV AX,ES:[DI].phys_seg_addr + CMP AX,CS:[SI].phys_seg_addr + jne check_map_data1 + ADD SI,SIZE phys_page_struct + ADD DI,SIZE phys_page_struct + LOOP check_map_data3 + CLC +check_map_data2: + POP DI SI CX AX + RET +check_map_data1: + STC + JMP check_map_data2 +check_map_data ENDP +;------ function 1 -------------------------------------------------- +; Get status +; output +; AH : status +;-------------------------------------------------------------------- +; Same as noerr +;------ function 2 -------------------------------------------------- +; Get page frame address +; output +; AH : status +; BX : page segment address +;-------------------------------------------------------------------- +func2: + STI + MOV BX,page_frame_seg ;get EMM physical page segment +f21: ; address. + MOV [BP].bx_save,BX + JMP noerr ;exit + +;------ function 3 -------------------------------------------------- +; Get unallocated page count +; output +; AH : status +; BX : unallocate page +; DX : all page +;-------------------------------------------------------------------- +func3: ;v0.5.... + MOV DX,total_pages ;Get total page count + MOV BX,un_alloc_pages ;Get unallocated page count + MOV [BP].dx_save,DX ;Save all page count + JMP f21 + +;------ function 4 -------------------------------------------------- +; Allocate pages +; input +; BX : request allocate page +; output +; AH : status +; DX : EMM handle +;-------------------------------------------------------------------- +func4: ;v0.6.... + OR BX,BX ;request page size 0 ? + JZ f49 ;yes +;------ function 27 ------------------------------------------------- +; Allocate raw pages +; input +; BX : num_of_raw_pages_to_alloc +; output +; AH : status +; DX : raw handle +;-------------------------------------------------------------------- +func27: + +f41: + CMP total_pages,BX ;request total size over ? + jb f42 ;yes + CMP un_alloc_pages,BX ;request unallocate size over ? + jb f43 ;yes + XOR SI,SI + MOV CX,HANDLE_CNT +f45: + CMP byte ptr [SI].handle_flag,0;not used EMM handle ? + je f44 + ADD SI,FLAG_SIZE ;add handle flag size + LOOP f45 + JMP err85 ;error exit +f44: + MOV DX,SI + SHR DX,1 + MOV byte ptr [SI].handle_flag,1;handle active flag set + INC handle_count ;used EMM handle count up + SUB un_alloc_pages,BX ;unallocated page - BX + MOV [SI].alloc_page_count,bl;EMM handle used page count set + MOV [SI].back_address,0 ;backup address clear + MOV DI,page_ptr + MOV [SI].page_address,DI ;set page buffer pointer + push cs + pop es + MOV SI,OFFSET log_page + XOR AX,AX + MOV CX,BX + jcxz f48 + jmp short f47 +f4a: + ADD SI,LOG_SIZE + INC AX +f47: + CMP WORD PTR [SI],NOT_USE ;unallocated page ? + JNZ f4a + MOV [SI],DX ;EMM handle set + STOSW ;logical page no. set + LOOP f4a +f48: + MOV [BP].dx_save,DX ;return EMM handle + MOV page_ptr,DI + JMP noerr ;exit +f49: + JMP err89 ;error exit +f42: + JMP err87 ;error exit +f43: + JMP err88 ;error exit + +;------ function 5 -------------------------------------------------- +; Map handle pages +; input +; AL : physical page no. +; BX : logical page no. (if BX=FFFFH then unmap) +; DX : EMM handle +; output +; AH : status +;-------------------------------------------------------------------- +func5: ;v0.6.... + CMP AL,PHYS_PAGES ;physical page no. ok ? + jnb f51 ;no + CMP DX,HANDLE_CNT ;check handle data... + jnb f5a + MOV SI,DX + SHL SI,1 + CMP byte ptr [SI].handle_flag,0;active handle ? + je f5a + MOV DI,OFFSET map_table ;get phys_page_struct pointer.. + mov cl,al + MOV AX,SIZE phys_page_struct + MUL CL + ADD DI,AX + CMP BX,UNMAP ;unmap ? + JZ f57 + CMP bl,[SI].alloc_page_count;logical page no. OK ? + jnb f53 + SHL BX,1 + ADD BX,[SI].page_address + MOV AX,[BX] +; OR AL,80h +f58: + CMP DX,[DI] ;same handle ? + JNZ f54 + CMP AL,[DI].log_page_data ;same page no. ? + JZ f56 +f54: + MOV [DI],DX ;set handle + MOV [DI].log_page_data,AL ;set logical page no. data + MOV DX,[DI].phys_page_port + OUT DX,AL +f56: + JMP noerr ;exit +f57: + xor al,al + MOV DX,bx + JMP f58 +f51: + JMP err8b ;error exit +f53: + JMP err8a ;error exit +f5a: + JMP err83 ;error exit + +;------ function 6 -------------------------------------------------- +; Deallocate pages +; input +; DX : EMM handle +; output +; AH : status +;-------------------------------------------------------------------- +f63: + JMP err86 ;error exit +func6: + push CS + pop ES + CMP DX,HANDLE_CNT ;check handle data... + JNC f5a + MOV BX,DX + SHL BX,1 + CMP byte ptr [BX].handle_flag,0;handle OK ? + JZ f5a + CMP [BX].back_address,0 ;backup used? + JNZ f63 + MOV cl,[BX].alloc_page_count + xor ch,ch + JCXZ f6c ;page = 0 ? + add un_alloc_pages,cx ;add unallocated pages + MOV DI,[BX].page_address ;deallocate logical page... + mov si,di + PUSH BX +f65: + MOV BX,[si] + SHL BX,1 + MOV [BX].log_page,NOT_USE + add si,2 + LOOP f65 + POP BX + MOV CX,page_ptr + SUB CX,SI + SHR CX,1 + JCXZ f62 + REPZ MOVSW +f62: + MOV cl,[BX].alloc_page_count + xor ch,ch + JCXZ f68 + MOV AX,UNALLOC + REPZ STOSW +f68: + XOR DI,DI ;change page address.... + MOV SI,[BX].page_address ;get page address. + MOV al,[BX].alloc_page_count;get allocated page count. + xor ah,ah + SHL AX,1 + MOV CX,handle_count + JMP short f66 +f6b: + ADD DI,FLAG_SIZE +f66: + CMP byte ptr [DI].handle_flag,0;active handle ? + JZ f6b + CMP [DI].page_address,SI ;page_address > SI ? + JNG f64 + SUB [DI].page_address,AX ;page address - AX +f64: + LOOP f6b + SUB page_ptr,AX ;SUB page pointer + MOV CX,PHYS_PAGES ;deallocate physical page... + XOR AL,AL + MOV SI,OFFSET map_table +f6a: + CMP [SI],DX ;same handle no.? + JNZ f67 + CALL reset_phys_page ;reset physical page. +f67: + INC AL + ADD SI,SIZE phys_page_struct + LOOP f6a +f6c: + MOV word ptr [BX].alloc_page_count,0 + MOV [BX].page_address,0 ;clear handle page pointer + MOV [BX].back_address,0 ;clear handle back pointer + cmp byte ptr f7_ver,32h + je f6e + MOV DI,OFFSET handle_name ;clear handle name data... + MOV AX,DX + MOV CL,3 + SHL AX,CL + ADD DI,AX + xor ax,ax + MOV CX,HANDLE_NAME_SIZE/2 + REPZ stosw +f6e: + OR DX,DX ;system handle? + JZ f6d + DEC handle_count ;not use handle count up + JMP noerr ;exit +f6d: + MOV byte ptr [BX].handle_flag,1 + JMP noerr ;exit + +;------ function 7 -------------------------------------------------- +; Get EMS version +; output +; AH : status +; AL : EMS version number +;-------------------------------------------------------------------- +func7: + STI +f7_ver equ $+1 + MOV AL,40h ;get version no. + JMP noerr + +;------ function 8 -------------------------------------------------- +; Save page map +; input +; DX : EMM handle +; output +; AH : status +;-------------------------------------------------------------------- +func8: ;v0.6.... + push CS + pop ES + CMP DX,HANDLE_CNT ;check handle data + JNC f81 + MOV SI,DX + SHL SI,1 + CMP byte ptr [SI].handle_flag,1;handle OK ? + JNZ f81 + CMP [SI].back_address,0 ;backup ? + JNZ f82 + MOV AL,backup_count + CMP AL,BACK_MAX + jb f83 +f84: + JMP err8c ;error exit +f83: + MOV DI,offset backup_flags ;copy mapping data -> [DI] + mov cx,BACK_MAX ;v1.01 + xor al,al + repnz scasb ;Search for free region + jnz f84 + dec di + mov byte ptr [di],1 ;Set busy flag + sub di,offset backup_flags + mov ax,di + mov cl,CONTEXT_SIZE + mul cl + add ax,offset backup_map + mov di,ax + MOV [SI].back_address,DI + MOV SI,OFFSET map_table + MOV CX,CONTEXT_SIZE/2 + REPZ MOVSW + INC backup_count + JMP noerr +f81: + JMP err83 +f82: + JMP err8d + +;------ function 9 -------------------------------------------------- +; Restore page map +; input +; DX : EMM handle +; output +; AH : status +;-------------------------------------------------------------------- +func9: + push CS + pop ES + CMP DX,HANDLE_CNT ;check handle data + JNC f81 + MOV BX,DX + SHL BX,1 + CMP byte ptr [BX].handle_flag,1;handle OK ? + JNZ f81 + CMP [BX].back_address,0 ;backup ? + JZ f92 + MOV CX,CONTEXT_SIZE/2 ;move mapping data... + MOV SI,[BX].back_address + MOV DI,OFFSET map_table + PUSH DI + REPZ MOVSW + POP DI + CALL set_pages_map ;enable physical pages... + DEC backup_count ;backup mapping count DEC + MOV ax,[BX].back_address ;v1.01 + sub ax,offset backup_map + mov cl,CONTEXT_SIZE + div cl + add ax,offset backup_flags + mov di,ax + mov byte ptr [di],0 ;Set free flag + MOV [BX].back_address,0 + JMP noerr ;exit +f92: + JMP err8e + +;------ function 10 ------------------------------------------------- +; Get page mapping register I/O port array +; input +; ES:DI : buffer address point +; output +; AH : status +; AL : board count +;-------------------------------------------------------------------- +; Not supported on 4.0 : err84 +;------ function 11 ------------------------------------------------- +; Get logical-to-physical page translation array +; input +; DX : EMM handle +; ES:DI : buffer address point +; output +; AH : status code +; BX : number of pages allocated EMM handle. +;-------------------------------------------------------------------- +; Not supported on 4.0 : err84 +;------ function 12 ------------------------------------------------- +; Get EMM handle count +; output +; AH : status +; BX : active EMM handles +;-------------------------------------------------------------------- +func12: + STI + MOV BX,handle_count +f121: + MOV [BP].bx_save,BX + JMP noerr ;exit + +;------ function 13 ------------------------------------------------- +; Get EMM handle pages +; input +; DX : EMM handle +; output +; AH : status +; BX : pages EMM handle +;-------------------------------------------------------------------- +func13: ;v0.6.... + STI + CMP DX,HANDLE_CNT ;check handle data + jnb f131 + MOV SI,DX + SHL SI,1 + CMP byte ptr [SI].handle_flag,1;handle OK ? + jne f131 + MOV bl,[SI].alloc_page_count + xor bh,bh + jmp f121 ;exit +f131: + JMP err83 ;error exit +;------ function 14 ------------------------------------------------- +; Get all EMM handle pages +; input +; ES:DI : buffer address point +; output +; AH : status +; BX : number of active EMM handles +;-------------------------------------------------------------------- +func14: + STI + XOR SI,SI + MOV CX,HANDLE_CNT + XOR BX,BX + XOR DX,DX +f142: + CMP byte ptr [SI].handle_flag,0 + JZ f141 + MOV AX,DX + STOSW + MOV al,[SI].alloc_page_count;v0.5 + xor ah,ah + STOSW + INC BX +f141: + INC DX + ADD SI,FLAG_SIZE + LOOP f142 + JMP f121 + +;------ function 15 ------------------------------------------------- +; Get/set page map +; input +; AL : request subfunction no. +; ES:DI : mapping registers buffer address point +; output +; AH : status +;-------------------------------------------------------------------- +func15: + cbw + dec ax + js get_page_map ; 0 + jz set_page_map ; 1 + dec ax + jz get_set_page_map ; 2 + dec ax + jz get_size_page_map ; 3 + jmp err84 ;error exit + +;-------------------------------------------------------------------- +; Get page map. +; input +; ES:DI : dest_page_map +; output +; AH : status +;-------------------------------------------------------------------- +get_page_map: + MOV SI,OFFSET map_table + MOV CX,CONTEXT_SIZE/2 + REPZ MOVSW + JMP noerr ;exit + +;-------------------------------------------------------------------- +; Set page map. +; input +; DS:SI : source_page_map +; output +; AH : status +;-------------------------------------------------------------------- +set_page_map: + MOV AX,[BP].ds_save + MOV DS,AX + MOV CX,CONTEXT_SIZE/2 + MOV AX,SS + MOV ES,AX + LEA DI,[BP].f15_map_data ;save map data. + REPZ MOVSW +set_page_map3: + LEA DI,[BP].f15_map_data + CALL check_map_data ;check map data (ES:DI) + JC set_page_map2 + MOV AX,ES + MOV DS,AX + MOV SI,DI + push cs + pop es + MOV DI,OFFSET map_table + MOV CX,CONTEXT_SIZE/2 + REPZ MOVSW + CALL set_pages_map ;mapping physical pages. + JMP noerr ;exit +set_page_map2: + JMP erra3 ;error exit + +;-------------------------------------------------------------------- +; Get & set page map. +; input +; DS:SI : source_page_map +; ES:DI : dest_page_map +; output +; AH : status +;-------------------------------------------------------------------- +get_set_page_map: + PUSH DI DS ES + MOV AX,[BP].ds_save + MOV DS,AX + MOV AX,SS + MOV ES,AX + LEA DI,[BP].f15_map_data + MOV CX,CONTEXT_SIZE/2 + REPZ MOVSW + POP ES DS DI + MOV SI,OFFSET map_table ;move current map data... + MOV CX,CONTEXT_SIZE/2 + REPZ MOVSW + MOV AX,SS + MOV ES,AX + JMP set_page_map3 + +;-------------------------------------------------------------------- +; Get size of page map save array. +; output +; AH : status +; AL : size_of_array +;-------------------------------------------------------------------- +get_size_page_map: + MOV AL,CONTEXT_SIZE ;map data size set. + JMP noerr +; +; This is end of EMS 3 function set +; +;------ function 16 ------------------------------------------------- +; Get/set partial page map +;-------------------------------------------------------------------- +func16: + cbw + dec ax + js get_partial_map ; 0 + jz set_partial_map ; 1 + dec ax + jz get_size_partial_map ; 2 + jmp err84 ;error exit +;-------------------------------------------------------------------- +; Get size of partial page map save array +; input +; BX : number of pages in the partial array +; output +; AH : status +; AL : size_of_partial_save_array +;-------------------------------------------------------------------- +get_size_partial_map: + OR BX,BX ;BX = 0? + JZ get_size_partial_map1 + CMP BX,PHYS_PAGES ;BX > physical page count? + JG get_size_partial_map2 + MOV AX,SIZE phys_page_struct;get size of partial map array. + MUL BL + ADD AX,2 + JMP noerr ;exit +get_size_partial_map1: + JMP err8f ;error exit +get_size_partial_map2: + JMP err8b ;error exit + +;-------------------------------------------------------------------- +; Get partial page map +; input +; DS:SI : partial_page_map +; ES:DI : dest_array +; output +; AH : status +;-------------------------------------------------------------------- +get_partial_map: + MOV AX,[BP].ds_save + MOV DS,AX + LODSW + CMP AX,PHYS_PAGES + JG get_partial_map1 ;rel. 0.2 + MOV CX,AX + JCXZ get_partial_map5 ;page count = 0? + STOSW +get_partial_map4: + LODSW + PUSH CX + MOV BX,OFFSET map_table + MOV CX,PHYS_PAGES +get_partial_map3: + CMP AX,CS:[BX].phys_seg_addr + JZ get_partial_map2 + ADD BX,SIZE phys_page_struct + LOOP get_partial_map3 + POP CX + JMP err8b ;error exit +get_partial_map2: + PUSH SI DS + PUSH CS + POP DS + MOV SI,BX + MOV CX,SIZE phys_page_struct + REPZ MOVSB + POP DS SI CX + LOOP get_partial_map4 +get_partial_map5: + JMP noerr ;exit +get_partial_map1: + JMP erra4 ;error exit + +;-------------------------------------------------------------------- +; Set partial page map +; input +; DS:SI : source_array +; output +; AH : status +;-------------------------------------------------------------------- +set_partial_map: + MOV AX,[BP].ds_save + MOV DS,AX + LODSW + MOV [BP].f16_map_len,AX ;save page map data length. + MOV CX,SIZE phys_page_struct + MUL CL + MOV CX,AX + JCXZ set_partial_map1 + MOV AX,SS ;save page map data... + MOV ES,AX + LEA DI,[BP].f16_map_data + REPZ MOVSB + LEA SI,[BP].f16_map_data ;set page map data... + MOV AX,ES + MOV DS,AX + MOV AX,CS + MOV ES,AX + MOV CX,[BP].f16_map_len ;get page map data length. +set_partial_map4: + MOV AX,[SI].phys_seg_addr + CALL change_seg_page ;change segment -> phys_page_no + JC set_partial_map3 + MOV DI,OFFSET map_table + PUSH CX + MOV CX,SIZE phys_page_struct + MUL CL + ADD DI,AX + REPZ MOVSB + POP CX + LOOP set_partial_map4 + CALL set_pages_map ;mapping physical pages. +set_partial_map1: + JMP noerr ;exit +set_partial_map3: + JMP err8b ;error exit + +;------ function 17 ------------------------------------------------- +; Map/unmap multiple handle pages +;-------------------------------------------------------------------- +func17: + STI + OR AL,AL + JZ log_phys_map + CMP AL,1 + JZ log_phys_map + JMP err84 ;error exit + +;-------------------------------------------------------------------- +; Logical page/physical page/segment method +; input +; AL : physical page/segment selector +; DX : EMM handle +; CX : logical to physical map length +; DS:SI : pointer to logical to physical/segment map array +; output +; AH : status +;-------------------------------------------------------------------- +log_phys_map: + MOV [BP].f17_ax_save,AX + MOV AX,[BP].ds_save + MOV DS,AX + CALL check_handle ;check handle data. + JC log_phys_map2 + CMP CX,PHYS_PAGES + ja log_phys_map1 + JCXZ log_phys_map9 + MOV [BP].f17_map_len,CX ;save page map data length. + MOV AX,SS + MOV ES,AX + LEA DI,[BP].f17_map_data ;save page map data. + SHL CX,1 + REPZ MOVSW + MOV AX,SS + MOV DS,AX + LEA SI,[BP].f17_map_data ;set page map data pointer. + MOV CX,[BP].f17_map_len ;get page map data length. +log_phys_map7: + mov bx,[si].log_page_number1;get logical page no. + cmp bx,UNMAP ;unmapping? + je log_phys_map6 + call check_log_page ;check logical page no. + jc log_phys_map3 ;error? + mov bx,ax ;set EMM logical page no. +log_phys_map6: + mov ax,[bp].f17_ax_save + or al,al ;subfunction 0? + jnz log_phys_map8 + mov ax,[si].phys_page_number1;get physical page no. + cmp ax,PHYS_PAGES ;check physical page no. + jb log_phys_map4 +log_phys_map1: + jmp err8b +log_phys_map8: + mov ax,[si].mappable_seg_addr;get mappable seg_address. + call change_seg_page ;change segment -> phys_page_no + jc log_phys_map1 +log_phys_map4: + cmp bx,UNMAP ;unmapping? + jz log_phys_mapa + call set_phys_page ;set physical page + jmp short log_phys_map5 +log_phys_mapa: + call reset_phys_page ;reset physical page +log_phys_map5: + add si,SIZE log_to_phys_map_struct; + loop log_phys_map7 +log_phys_map9: + jmp noerr ;exit +log_phys_map2: + jmp err83 +log_phys_map3: + jmp err8a + +;------ function 18 ------------------------------------------------------ +; Reallocate pages +; input +; DX : EMM handle +; BX : reallocation count +; output +; AH : status +; BX : number of pages allocated to handle after reallocation +;------------------------------------------------------------------------- +f182: + JMP err87 +f181: + MOV word ptr [BP].bx_save,0 + JMP err83 +func18: + push CS + pop ES + CMP DX,HANDLE_CNT ;check handle data... + jnb f181 + MOV SI,DX + SHL SI,1 + CMP byte ptr [SI].handle_flag,0 + je f181 + CMP total_pages,BX ;request total size over ? + JC f182 ;yes + MOV al,[SI].alloc_page_count;get page size to handle + xor ah,ah + OR BX,BX ;reallocate count = 0? + JNZ f184 + MOV CX,AX + JCXZ f18a ;CX = 0 case? + MOV DI,[SI].page_address ;BX = 0 case... + add un_alloc_pages,ax ;add unallocated pages + PUSH BX +f185: + MOV BX,[DI] + SHL BX,1 + MOV [BX].log_page,NOT_USE ;unallocate logical page + add di,2 + LOOP f185 + POP BX + JMP short f18l +f184: + CMP AX,BX ;check reallocation/allocated + JNZ f18c ;pages. +f18a: + JMP noerr ;same size case. +f18c: + JNC f183 ;BX < allocated count? + JMP f186 +f183: + MOV CX,AX ;BX < allocated pages case... + SUB CX,BX + MOV DI,[SI].page_address ;BX = 0 case... + MOV AX,BX + SHL AX,1 + ADD DI,AX + add un_alloc_pages,cx ;add unallocated pages + PUSH BX +f18b: + MOV BX,[DI] + SHL BX,1 + MOV [BX].log_page,NOT_USE ;unallocate logical page + add di,2 + LOOP f18b + POP BX +f18l: + MOV CX,page_ptr ;clear & sort page buffer... + MOV AX,BX + SHL AX,1 + ADD AX,[SI].page_address + SUB CX,AX + PUSH SI + MOV DI,[SI].page_address + MOV AX,BX + SHL AX,1 + ADD DI,AX + MOV al,[SI].alloc_page_count + xor ah,ah + MOV SI,[SI].page_address + SHL AX,1 + ADD SI,AX + SHR CX,1 + JCXZ f18e + REPZ MOVSW +f18e: + MOV CX,page_ptr + SUB CX,DI + SHR CX,1 + JCXZ f18f + MOV AX,UNALLOC + REPZ STOSW +f18f: + POP SI + MOV al,[SI].alloc_page_count + xor ah,ah + MOV [SI].alloc_page_count,bl;set EMM handle used page count + XOR DI,DI ;change other handle page add- + SUB AX,BX ;ress.... + SHL AX,1 + MOV BX,[SI].page_address + MOV CX,handle_count + JMP short f18j +f18k: + ADD DI,FLAG_SIZE +f18j: + CMP byte ptr [DI].handle_flag,0;active handle ? + JZ f18k + CMP [DI].page_address,BX ;page_address > BX ? + JNG f18m + SUB [DI].page_address,AX ;page_address - AX +f18m: + LOOP f18k + SUB page_ptr,AX ;page_ptr - AX + CMP [SI].alloc_page_count,0 ;allocate page count = 0 ? + JNZ f18o + MOV [SI].page_address,0 ;clear page buffer pointer +f18o: + JMP noerr ;exit. +f187: + MOV al,[SI].alloc_page_count + xor ah,ah + MOV [BP].bx_save,AX + JMP err88 ;error exit +f186: + MOV CX,BX ;BX > allocated pages case... + SUB CX,AX + cmp un_alloc_pages,cx ;request unallocate size over ? + jb f187 ;no + PUSH SI ;move page buffer... + MOV DI,page_ptr + CMP [SI].page_address,0 ;not poniter address? + JNZ f18p + MOV [SI].page_address,DI ;set page pointer + JMP short f18q +f18p: + DEC DI + MOV AX,CX + SHL AX,1 + ADD DI,AX + MOV al,[SI].alloc_page_count + xor ah,ah + SHL AX,1 + ADD AX,[SI].page_address + PUSH CX + MOV CX,page_ptr + SUB CX,AX + MOV SI,page_ptr + DEC SI + STD + JCXZ f18g + REPZ MOVSB +f18g: + POP CX +f18q: + SHL CX,1 + ADD page_ptr,CX ;pointer add + POP SI + CLD + MOV DI,[SI].page_address ;allocate add pages... + MOV al,[SI].alloc_page_count + xor ah,ah + MOV CX,BX + SUB CX,AX + SHL AX,1 + ADD DI,AX + PUSH SI + MOV SI,OFFSET log_page + XOR AX,AX + sub un_alloc_pages,cx + JMP short f188 +f189: + ADD SI,LOG_SIZE + INC AX +f188: + CMP WORD PTR [SI],UNMAP ;logical page end? + JZ f18d + CMP WORD PTR [SI],NOT_USE ;unallocated page ? + JNZ f189 + MOV WORD PTR [SI],DX + STOSW + LOOP f189 + POP SI + MOV al,[SI].alloc_page_count + xor ah,ah + MOV [SI].alloc_page_count,bl;set EMM handle used page count + XOR DI,DI ;change other handle page add- + XCHG AX,BX ;ress.... + SUB AX,BX + SHL AX,1 + MOV BX,[SI].page_address + MOV CX,handle_count + JMP short f18h +f18i: + ADD DI,FLAG_SIZE +f18h: + CMP byte ptr [DI].handle_flag,0 + JZ f18i + CMP [DI].page_address,BX + JNG f18n + ADD [DI].page_address,AX +f18n: + LOOP f18i + JMP noerr ;exit +f18d: + POP SI + JMP err80 ;error exit +;------ function 19 ------------------------------------------------- +; Get/set handle attribute +;-------------------------------------------------------------------- +func19: + sti + cbw + dec ax + js get_handle_attr ; 0 + jz set_handle_attr ; 1 + dec ax + jz get_attr_cap ; 2 + jmp err84 ;error exit +;-------------------------------------------------------------------- +; Get handle attribute +; input +; DX : EMM handle +; output +; AH : status +; AL : handle attribute +;-------------------------------------------------------------------- +get_handle_attr: + CALL check_handle ;check handle data + JC get_handle_attr1 + MOV AL,VOLATILE ;handle attribute set + JMP noerr ;exit +get_handle_attr1: + JMP err83 ;error exit +;-------------------------------------------------------------------- +; Set handle attribute +; input +; DX : EMM handle +; BL : new handle attribute +; output +; AH : status +;-------------------------------------------------------------------- +set_handle_attr: + JMP err91 ;error exit +;-------------------------------------------------------------------- +; Get attribute capability +; output +; AH : status +; AL : attribute capability +;-------------------------------------------------------------------- +get_attr_cap: + mov al,VOLATILE ;set attribute capability + jmp noerr ;exit +;------ function 20 ------------------------------------------------- +; Get/set handle name +;-------------------------------------------------------------------- +func20: + dec al + js get_handle_name ; 0 + jz set_handle_name ; 1 + jmp err84 ;error exit +;-------------------------------------------------------------------- +; Get handle name +; input +; DX : EMM handle +; ES:DI : pointer to handle name array +; output +; AH : status +;-------------------------------------------------------------------- +get_handle_name: + CALL check_handle ;check handle data + JC get_handle_name1 + MOV SI,OFFSET handle_name + MOV AX,DX + MOV CL,3 + SHL AX,CL + ADD SI,AX + MOV CX,HANDLE_NAME_SIZE/2 + REPZ MOVSW + JMP noerr ;exit +get_handle_name1: + JMP err83 ;error exit +;-------------------------------------------------------------------- +; Set handle name +; input +; DX : EMM handle +; DS:SI : pointer to handle name +; output +; AH : status +;-------------------------------------------------------------------- +set_handle_name: + call check_handle ;check handle data + jc get_handle_name1 + push cs + pop es + mov ax,[bp].ds_save + mov ds,ax + mov cx,HANDLE_CNT ;check handle name... + mov di,offset handle_name + mov bx,offset handle_flag +set_handle_name2: + cmp byte ptr [bx],0 ;active handle ? + je set_handle_name3 + push cx si + mov cx,HANDLE_NAME_SIZE/2 + repz cmpsw ;compare handle name... + pop si cx + je set_handle_name4 ;found same handle name ? +set_handle_name3: + add bx,2 + loop set_handle_name2 + mov di,offset handle_name ;set handle name... + mov cl,3 + shl dx,cl + add di,dx + mov cx,HANDLE_NAME_SIZE/2 + rep movsw + jmp noerr ;exit +set_handle_name4: + jmp erra1 ;error exit +;------ function 21 ------------------------------------------------- +; Get handle directory +;-------------------------------------------------------------------- +func21: + dec al + js get_handle_dir ; 0 + JZ search_for_name ; 1 + dec al + JZ get_total_handle ; 2 + JMP err84 ;error exit +;-------------------------------------------------------------------- +; Get handle directory +; input +; ES:DI : pointer to handle_dir +; output +; AH : status +; AL : number of entries in the handle_dir array +;-------------------------------------------------------------------- +get_handle_dir: + MOV CX,HANDLE_CNT + MOV SI,OFFSET handle_name + XOR DX,DX + XOR BL,BL +get_handle_dir1: + CALL check_handle ;check handle data + JC get_handle_dir2 + MOV AX,DX ;set EMM handle. + STOSW + PUSH CX SI ;set handle name... + MOV CX,HANDLE_NAME_SIZE/2 + REPZ MOVSW + POP SI CX + INC BL ;inc handle count. +get_handle_dir2: + ADD SI,HANDLE_NAME_SIZE + INC DX + LOOP get_handle_dir1 + MOV AL,BL + JMP noerr ;exit +;-------------------------------------------------------------------- +; Search for named handle +; input +; DS:SI : search handle_name pointer +; output +; AH : status +; DX : EMM handle +;-------------------------------------------------------------------- +search_for_name: + push CS + pop ES + MOV CX,HANDLE_CNT + MOV DI,OFFSET handle_name + MOV AX,[BP].ds_save + MOV DS,AX + XOR DX,DX +search_for_name1: + PUSH CX SI di + MOV CX,HANDLE_NAME_SIZE/2 + repz cmpsw + POP di SI CX + JZ search_for_name2 + add di,HANDLE_NAME_SIZE + inc dx + loop search_for_name1 + jmp erra0 +search_for_name2: + mov cx,HANDLE_NAME_SIZE/2 + xor ax,ax + repz scasw + jnz search_for_name3 + jmp erra1 ;error exit +search_for_name3: + push cx + pop ds + mov [bp].dx_save,dx + jmp noerr ;exit +;-------------------------------------------------------------------- +; Get total handle +; output +; AH : status +; BX : total_handles +;-------------------------------------------------------------------- +get_total_handle: + MOV BX,HANDLE_CNT ;set max handle count. + MOV [BP].bx_save,BX + JMP noerr ;exit +;------ function 22 ------------------------------------------------- +; Alter page map & jump. +; input +; AL : physical page number/segment selector +; DX : EMM handle +; DS:SI : pointer to map_and_jump structure +; output +; AH : status +;-------------------------------------------------------------------- +f224: + JMP err8a +func22: + STI + cmp AL,0 + je f220 + cmp AL,1 + je f220 + JMP err8f +f220: + MOV [BP].f22_ax_save,AX + CALL check_handle ;check handle data. + JC f221 + MOV AX,[BP].ds_save ;copy calling parameters... + MOV DS,AX + LES BX,[SI].target_address1 + MOV AX,ES + MOV [BP].f22_target_off,BX ;offset + MOV [BP].f22_target_seg,AX ;segment + MOV CL,[SI].log_phys_map_len;get mapping data length. + XOR CH,CH + MOV [BP].f22_map_len,CX ;length + JCXZ f22a + LES BX,[SI].log_phys_map_ptr;get log_phys_map_ptr. + LEA DI,[BP].f22_map_data ;copy log_phys_map data... + SHL CX,1 +f228: + MOV AX,ES:[BX] + MOV SS:[DI],AX + add DI,2 + add BX,2 + LOOP f228 +f22a: + MOV AX,SS + MOV DS,AX + MOV CX,[BP].f22_map_len ;length + JCXZ f222 + LEA DI,[BP].f22_map_data ;get mapping data pointer. +f223: + MOV BX,[DI].log_page_number1;get logical page no. + CMP BX,UNMAP ;unmapping? + JZ f22b + CALL check_log_page ;check logical page no. + JC f224 + MOV BX,AX ;set EMM logical page no. +f22b: + MOV AX,[BP].f22_ax_save ;get phys_page_no/seg_selector. + OR AL,AL ;sub_function 0? + JNZ f229 + MOV AX,[DI].phys_page_number1;get physical page no. + CMP AX,PHYS_PAGES + jb f225 +f22c: + jmp err8b +f229: + MOV AX,[DI].mappable_seg_addr;get mappable segment. + CALL change_seg_page ;change segment -> phys_page_no. + JC f22c +f225: + CMP BX,UNMAP ;unmapping? + JZ f227 + CALL set_phys_page ;set physical page + jmp short f226 +f221: + JMP err83 +f227: + CALL reset_phys_page ;reset physical page +f226: + ADD DI,SIZE log_to_phys_map_struct; + LOOP f223 +f222: + MOV AX,[BP].f22_target_seg ;get target address. + MOV [BP].ret_segment,AX ;set FAR:JUMP segment. + MOV AX,[BP].f22_target_off ;get target address. + MOV [BP].ret_offset,AX ;set FAR:JUMP offset. + JMP noerr ;exit +;------ function 23 ------------------------------------------------- +; Alter page map & call +;-------------------------------------------------------------------- +func23: + STI + or al,al + je f2300 + cmp al,1 + je f2300 + cmp al,2 + je get_page_map_stack + jmp err84 +;-------------------------------------------------------------------- +; Get page map stack space size +; output +; AH : status +; BX : stack space required +;-------------------------------------------------------------------- +get_page_map_stack: + MOV BX,RET_SP ;set stack space... + MOV [BP].bx_save,BX + JMP noerr ;exit +;-------------------------------------------------------------------- +; Alter page map & call +; input +; AL : physical page number/segment selector +; DX : EMM handle +; DS:SI : pointer to map_and_call structure +; output +; AH : status +; AL : number of entries in the handle_dir array +;-------------------------------------------------------------------- +f2300: + MOV [BP].f23_ax_save,AX + CALL check_handle ;check handle data + JC f221 + MOV AX,[BP].ds_save + MOV DS,AX + LES BX,[SI].target_address2 ;get FAR:CALL target_addr. + MOV [BP].f23_target_off,BX ;set offset. + MOV AX,ES ;get segment + MOV [BP].f23_target_seg,AX ;set segment. + MOV CL,[SI].new_page_map_len;get new_page_map_len. + XOR CH,CH + MOV [BP].f23_new_map_len,CX + LES BX,[SI].new_page_map_ptr;get new_page_map_ptr. + JCXZ f2303 + LEA DI,[BP].f23_new_map_data; + SHL CX,1 +f2302: + MOV AX,ES:[BX] + MOV SS:[DI],AX + add DI,2 + add BX,2 + LOOP f2302 +f2303: + MOV CL,[SI].old_page_map_len;get old_page_map_len. + XOR CH,CH + MOV [BP].f23_old_map_len,CX + LES BX,[SI].old_page_map_ptr;get old_page_map_ptr. + JCXZ f2305 + LEA DI,[BP].f23_old_map_data; + SHL CX,1 +f2304: + MOV AX,ES:[BX] + MOV SS:[DI],AX + add DI,2 + add BX,2 + LOOP f2304 +f2305: + MOV CX,[BP].f23_new_map_len ;get new_page_map_len. + JCXZ f2307 ;mapping page length = 0? + MOV AX,SS + MOV DS,AX + LEA SI,[BP].f23_new_map_data;get new_page_map_ptr. +f2306: + MOV BX,[SI].log_page_number2;get logical page no. + CMP BX,UNMAP ;unmapping? + JZ f2313 + CALL check_log_page + JC f2309 + MOV BX,AX +f2313: + MOV AX,[BP].f23_ax_save + OR AL,AL ;sub_function 0? + JZ f2310 + MOV AX,[SI].mappable_seg_addr; + CALL change_seg_page ;change segment -> phys_page_no. + JC f2314 +f2310: + MOV AX,[SI].phys_page_number1;get physical page no. + CMP AX,PHYS_PAGES + jnb f2314 +f2311: + CMP BX,UNMAP ;unmapping? + JZ f2312 + CALL set_phys_page ;set physical page + jmp short f2308 +f2309: + JMP err8a +f2314: + JMP err8b +f2312: + CALL reset_phys_page ;reset physical page +f2308: + ADD SI,SIZE log_to_seg_map_struct; + LOOP f2306 +f2307: + MOV BX,OFFSET f2350 ;get FAR:CALL return_addr + MOV [BP].f23_retoff,BX ;set offset. + MOV AX,CS + MOV [BP].f23_retseg,AX ;set segment. + MOV AX,[BP].ret_flag ;get flags. + MOV [BP].f23_flag,AX ;set flags. + MOV AH,0 + POP BX CX DX SI DI BP ES DS + IRET ;FAR:CALL to target + +; +; far call return point +; +f2350: + PUSHF ;push flags. + POP AX ;pop flags. + CLI + SUB SP,F23_RETSP + PUSH DS ES BP DI SI DX CX BX + MOV BP,SP + MOV [BP].ret_flag,AX ;set return_flags. + MOV CX,[BP].f23_old_map_len ;get old_page_map_len. + JCXZ f2351 ;mapping page length = 0? + MOV AX,SS + MOV DS,AX + LEA SI,[BP].f23_old_map_data;get old_page_map_ptr. +f2352: + MOV BX,[SI].log_page_number2;get logical page no. + CMP BX,UNMAP ;unmapping? + JZ f2359 + CALL check_log_page + JC f2309 + MOV BX,AX +f2359: + MOV AX,[BP].f23_ax_save + OR AL,AL + JZ f2354 + MOV AX,[SI].mappable_seg_addr + CALL change_seg_page ;change segment -> phys_page_no. + jc f2314 +f2354: + MOV AX,[SI].phys_page_number1;get physical page no. + CMP AX,PHYS_PAGES + jnb f2314 + CMP BX,UNMAP ;unmapping? + JZ f2357 + CALL set_phys_page ;set physical page + jmp short f2353 +f2357: + CALL reset_phys_page ;reset physical page +f2353: + ADD SI,SIZE log_to_seg_map_struct + LOOP f2352 +f2351: + JMP noerr + +;------ Function 24 (57h) ------------------------------------------- +; Move Memory Region + +; This subfunction copies a region of memory in the following memory +; source/destination combinations: +; +; o conventional memory to conventional memory +; o conventional memory to expanded memory +; o expanded memory to conventional memory +; o expanded memory to expanded memory +; +; AL : Operation (0) +; DS:SI : pointer to move_info +; AH : Return code +;-------------------------------------------------------------------- +func24: + or al,al + je f2400 + cmp al,1 + je f2400 + jmp err84 ; +f2400: + mov [bp].f24_al_save,al + mov ax,[bp].ds_save + mov ds,ax + mov ax,[si].source_offset ; + mov [bp].source_off,ax + mov al,[si].source_type + mov [bp].source_type1,al + or al,al + je f2401 + mov ax,[si].source_seg_page ; = EMS + mov [bp].source_page,ax + mov ax,cs:Page_Frame_Seg + mov [bp].source_seg,ax + mov ax,[si].source_handle1 + mov [bp].source_handle2,ax + jmp short f2402 +f2401: + mov ax,[si].source_seg_page ; = RAM + mov [bp].source_seg,ax +f2402: + mov ax,[si].dest_offset ; + mov [bp].dest_off,ax + mov al,[si].dest_type + mov [bp].dest_type1,al + or al,al + je f2403 + mov ax,[si].dest_seg_page ; = EMS + mov [bp].dest_page,ax + mov ax,cs:Page_Frame_Seg + add ax,400H + mov [bp].dest_seg,ax + mov ax,[si].dest_handle1 + mov [bp].dest_handle2,ax + jmp short f2404 +f2403: + mov ax,[si].dest_seg_page ; = RAM + mov [bp].dest_seg,ax +f2404: + les di,[si].region_lenght ; + mov [bp].region_low,di + mov ax,es + mov [bp].region_high,ax + cmp ax,10h ; + jb f2405 + jne f2407 + or di,di + jnz f2407 + +f2405: + cmp [si].source_type,0 + jne f2408 ; = RAM + FarPtrAddress [bp].source_seg,[bp].source_off + cmp dx,10h ;... + jnb f2411 +f2409: + Save32 [bp].source_ea_high,[bp].source_ea_low; + Add32 [bp].region_high,[bp].region_low + Sub32 0,1 ; + cmp dx,10h ; + jb f2410 + jg f2411 + or ax,ax + jz f2410 +f2411: + jmp errA2 +f2413: + jmp err8A +f2414: + jmp err95 +f2410a: + jmp err93 +f2412: + jmp err83 +f2407: + jmp err96 +f2418: + jmp errA2 +f2408: + mov dx,[bp].source_handle2 ; = EMS + call check_handle ; + jc f2412 + mov bx,[bp].source_page + call check_log_page ; + jc f2413 + mov di,dx + mov ax,[bp].source_off + cmp ax,4000h + jnb f2414 + xor dx,dx + Add32 [bp].region_high,[bp].region_low + Sub32 0,1 + Shl32 2 + add bx,dx + mov dx,di + call check_log_page ; + jc f2410a +f2410: + cmp [si].dest_type,0 + jne f2415 ; = RAM + FarPtrAddress [bp].dest_seg,[bp].dest_off + cmp dx,10h ;. + jnb f2418 + Save32 [bp].dest_ea_high, [bp].dest_ea_low + Add32 [bp].region_high,[bp].region_low + Sub32 0,1 ; + cmp dx,10h ; + jb f2417 + jmp short f2418 +f2419: + jmp err83 +f2420: + jmp err8A +f2421: + jmp err95 ; +f2417a: + jmp err93 ; +f2415: + mov dx,[bp].dest_handle2 ; = EMS + call check_handle ; + jc f2419 + mov bx,[bp].dest_page + call check_log_page ; + jc f2420 + mov di,dx + mov ax,[bp].dest_off + cmp ax,4000h + jnb f2421 + xor dx,dx + Add32 [bp].region_high, [bp].region_low + Sub32 0,1 + Shl32 2 + add bx,dx + mov dx,di + call check_log_page ; + jc f2417a + +f2417: + mov [bp].direct_move,0 + mov al,[si].source_type + cmp al,[si].dest_type ; + jne f2423 +f2422: + cmp al,1 + je f2424 + FLoad32 [bp].source_ea_low + mov bx,[bp].dest_ea_low ; = RAM + mov cx,[bp].dest_ea_high + jmp short f2430 +f2424: + mov ax,[bp].source_handle2 ; = EMS + cmp ax,[bp].dest_handle2 + jne f2423 + mov dx,[bp].dest_page + xor ax,ax + Shr32 2 + Add32 0,[bp].dest_off + mov bx,ax + mov cx,dx + mov dx,[bp].source_page + xor ax,ax + Shr32 2 + Add32 0,[bp].source_off +f2430: + cmp dx,cx ;DX:AX = , CX:BX = + jne f2425 + cmp ax,bx +f2425: + jae f2426 + xchg bx,ax + xchg cx,dx + cmp [bp].f24_al_save,1 + je f2426 + or [bp].direct_move,1 ; +f2426: + sub ax,bx + sbb dx,cx + cmp dx,[bp].region_high + jne f2427 + cmp ax,[bp].region_low +f2427: + jae f2423 + cmp [bp].f24_al_save,1 + je f2428 ; + or [bp].direct_move,2 ; +f2423: + mov [bp].zero_low,0 + test [bp].direct_move,1 + jnz f2429 + cld + jmp f2435 +f2428: + jmp err97 + +f2429: + std + cmp [si].dest_type,1 ; = EMS ? + je f2432 + + FLoad32 [bp].dest_ea_low + Add32 [bp].region_high,[bp].region_low + Sub32 0,1 + mov bx,ax + and bx,000Fh + mov [bp].dest_off,bx + Shr32 4 + mov [bp].dest_seg,ax + jmp short f2433 +f2432: ; EMS... + FLoad32 [bp].region_low + Add32 0,[bp].dest_off + Sub32 0,1 + mov bx,ax + and bx,3FFFh + mov [bp].dest_off,bx + Shl32 2 + mov bx,[bp].dest_page + add bx,dx + mov [bp].dest_page,bx + mov dx,[bp].dest_handle2 + call check_log_page + mov bx,ax + mov al,1 + call set_phys_page +f2433: + cmp [si].source_type,1 ; = EMS ? + je f2434 + ;... + FLoad32 [bp].source_ea_low + Add32 [bp].region_high,[bp].region_low + Sub32 0,1 + mov bx,ax + and bx,000Fh + mov [bp].source_off,bx + Shr32 4 + mov [bp].source_seg,ax + jmp short f2435 +f2434: ; EMS... + FLoad32 [bp].region_low + Add32 0,[bp].source_off + Sub32 0,1 + mov bx,ax + and bx,3FFFh + mov [bp].source_off,bx + Shl32 2 + add [bp].source_page,dx + mov dx,[bp].source_handle2 + call check_log_page + mov bx,ax + xor al,al + call set_phys_page + + +f2435: + mov al,[si].source_type ; + or al,[si].dest_type ; + jz f2436 + mov cx,SIZE phys_page_struct + mov si,offset map_table + mov di,offset f24_data + mov ax,cs + mov ds,ax + mov es,ax + rep movsw + or [bp].direct_move,4 + +f2436: + mov ax,[bp].region_low + or ax,[bp].region_high + jnz f2438 + test [bp].direct_move,4 ; + jz f2439 + mov cx,SIZE phys_page_struct + mov si,offset f24_data + mov di,offset map_table +f2440: + mov ax,cs + mov ds,ax + mov es,ax + rep movsw + call set_pages_map +f2439: + test [bp].direct_move,2 ; F24 !!! + jnz f2441 + jmp noerr +f2441: + jmp err92 + + +f2438: + cmp [bp].source_type1,1 + je f2442 + + FarPtrAddress [bp].source_seg,[bp].source_off + test [bp].direct_move,1 + jnz f2443 + Add32 [bp].zero_low,0 ; + mov bx,ax + and bx,000Fh + mov [bp].source_off,bx + Shr32 4 + mov [bp].source_seg,ax + jmp short f2444 +f2443: + Sub32 0,[bp].zero_low ; + mov bx,ax + or bx,0FFF0h + mov [bp].source_off,bx + Sub32 0,bx + Shr32 4 + mov [bp].source_seg,ax + jmp short f2444 +f2442: + mov ax,[bp].source_off ; EMS... + test [bp].direct_move,1 + jnz f2445 + add ax,[bp].zero_low ;... + cmp ax,4000h + jb f2446 + inc [bp].source_page + mov [bp].source_off,0 + jmp short f2446 +f2445: + sub ax,[bp].zero_low ;... + jnc f2446 + dec [bp].source_page + mov [bp].source_off,3FFFh +f2446: + mov dx,[bp].source_handle2 + mov bx,[bp].source_page + call check_log_page + mov bx,ax + xor al,al + call set_phys_page + + +f2444: + test [bp].dest_type1,1 + jnz f2447 + + FarPtrAddress [bp].dest_seg,[bp].dest_off + test [bp].direct_move,1 + jnz f2448 + Add32 0,[bp].zero_low ; + mov bx,ax + and bx,000Fh + mov [bp].dest_off,bx + Shr32 4 + mov [bp].dest_seg,ax + jmp short f2449 +f2448: + Sub32 0,[bp].zero_low ;... + mov bx,ax + or bx,0FFF0h + mov [bp].dest_off,bx + Sub32 0,bx + Shr32 4 + mov [bp].dest_seg,ax + jmp short f2449 +f2447: + mov ax,[bp].dest_off ; EMS... + test [bp].direct_move,1 + jnz f2450 + add ax,[bp].zero_low ;... + cmp ax,4000h + jb f2451 + inc [bp].dest_page + mov [bp].dest_off,0 + jmp short f2451 +f2450: + sub ax,[bp].zero_low ;... + jnc f2451 + dec [bp].dest_page + mov [bp].dest_off,3FFFh +f2451: + mov dx,[bp].dest_handle2 + mov bx,[bp].dest_page + call check_log_page + mov bx,ax + mov al,1 + call set_phys_page +f2449: + mov bl,[bp].dest_type1 ;MAXLEN (dest)... + mov ax,[bp].dest_off + call maxlen + push ax + mov bl,[bp].source_type1 ;MAXLEN (source)... + mov ax,[bp].source_off + call maxlen + pop bx + mov cx,ax + FLoad32 [bp].region_low + cmp cx,bx ; + jb f2452 + mov cx,bx +f2452: + or dx,dx + jnz f2453 + cmp cx,ax + jb f2453 + mov cx,ax + + +f2453: + mov [bp].zero_low,cx + mov ax,[bp].source_seg + mov ds,ax + mov ax,[bp].dest_seg + mov es,ax + mov si,[bp].source_off + mov di,[bp].dest_off + + cmp [bp].f24_al_save,1 + je f2454 + rep movsb ; +f2455: + FLoad32 [bp].region_low + Sub32 0,[bp].zero_low + Save32 [bp].region_high,[bp].region_low + jmp f2436 +f2454: + Exbyte ;... + loop f2454 + jmp f2455 +;------ function 25 ------------------------------------------------- +; Get mappable physical address array +;-------------------------------------------------------------------- +func25: + STI + DEC AL + js get_map_phys_addr ; 0 + JZ get_map_phys_ent ; 1 + JMP err84 ;error exit +;-------------------------------------------------------------------- +; Get mappable physical address array +; input +; ES:DI : mappable_phys_page +; output +; AH : status +; CX : number of entries in the mappable_phys_page +;-------------------------------------------------------------------- +get_map_phys_addr: + MOV AX,[BP].es_save + MOV ES,AX + MOV CX,PHYS_PAGES + MOV SI,OFFSET map_table + XOR DX,DX +get_map_phys_addr1: + MOV AX,[SI].phys_seg_addr + STOSW + MOV AX,DX + STOSW + INC DX + ADD SI,SIZE phys_page_struct + LOOP get_map_phys_addr1 +;-------------------------------------------------------------------- +; Get mappable physcal address array entries +; output +; AH : status +; CX : number of entries in the mappable_phys_page +;-------------------------------------------------------------------- +get_map_phys_ent: +get_map_phys_addr2: + MOV CX,PHYS_PAGES + MOV [BP].cx_save,CX ;set segment addr entrie + JMP noerr ;exit + +;------ function 26 ------------------------------------------------- +; Get expanded memory hardware infomation +;-------------------------------------------------------------------- +func26: + STI + DEC AL + js get_hardware_config ; 0 + JZ get_unalloc_raw_page ; 1 + JMP err84 ;error exit +;-------------------------------------------------------------------- +; Get hardware configration array +; input +; ES:DI : hardware_info +; output +; AH : status +;-------------------------------------------------------------------- +get_hardware_config: + CMP OSE_flag,0 ;OS/E flag enable? + jne get_hardware_config1 + MOV AX,[BP].es_save + MOV ES,AX + MOV AX,RAW_PAGES + STOSW + MOV AX,ALTER_REGS + STOSW + MOV AX,CONTEXT_SIZE + STOSW + MOV AX,DMA_REGS + STOSW + MOV AX,DMA_CHANNEL + STOSW + JMP noerr ;exit +get_hardware_config1: + JMP erra4 ;error exit +;-------------------------------------------------------------------- +; Get unallocated raw page count +; output +; AH : status +; BX : unallocated raw pages +; DX : total raw pages +;-------------------------------------------------------------------- +get_unalloc_raw_page: + JMP func3 ;goto function 3 +;------ function 28 ------------------------------------------------- +; Alternate map register set +;-------------------------------------------------------------------- +f280: + JMP erra4 ;error exit +func28: + STI + CMP OSE_flag,0 ;OS/E flag enable? + jne f280 + cbw + dec ax + js get_alter_map_reg ; 0 + JZ set_alter_map_reg ; 1 + dec ax + jz get_alter_map_size ; 2 + dec ax + jz alloc_alter_map_reg ; 3 + dec ax + jz dealloc_alter_map_reg ; 4 + dec ax + jz alloc_DMA_reg ; 5 + dec ax + jz enable_DMA_alter_reg ; 6 + dec ax + jz disable_DMA_alter_reg ; 7 + dec ax + jz dealloc_DMA_reg ; 8 + jmp err84 ;error exit +;-------------------------------------------------------------------- +; Get alternate map save array size +; output +; AH : status +; DX : size_of_array +;-------------------------------------------------------------------- +get_alter_map_size: + MOV DX,CONTEXT_SIZE + MOV [BP].dx_save,DX + JMP noerr ;exit +;-------------------------------------------------------------------- +; Allocate alternate map register set +; output +; AH : status +; BL : alternate map register set number +;-------------------------------------------------------------------- +alloc_alter_map_reg: +;-------------------------------------------------------------------- +; Allocate DMA register set +; output +; AH : status +; BL : DMA register set number +;-------------------------------------------------------------------- +alloc_DMA_reg: + xor bx,bx + MOV [BP].bx_save,BX + JMP noerr ;exit +;-------------------------------------------------------------------- +; Deallocate alternate map register set +; input +; BL : alternate map register set number +; output +; AH : status +;-------------------------------------------------------------------- +dealloc_alter_map_reg: +;-------------------------------------------------------------------- +; Enable DMA on alternate map register set +; input +; BL : DMA register set number +; DL : DMA channel number +; output +; AH : status +;-------------------------------------------------------------------- +enable_DMA_alter_reg: +;-------------------------------------------------------------------- +; Disable DMA on alternate map register set +; input +; BL : alternate register set number +; output +; AH : status +;-------------------------------------------------------------------- +disable_DMA_alter_reg: +;-------------------------------------------------------------------- +; Deallocate DMA register set +; input +; BL : DMA register set number +; output +; AH : status +;-------------------------------------------------------------------- +dealloc_DMA_reg: + OR BL,BL + jnz dealloc_alter_map_reg1 + JMP noerr +dealloc_alter_map_reg1: + JMP err9c +;-------------------------------------------------------------------- +; Get alternate map register set +; output +; AH : status +; BL : current active alternate map register set number +; ES:DI : pointer to a map register context save area +;-------------------------------------------------------------------- +get_alter_map_reg: + MOV DI,alter_map_off + MOV AX,alter_map_seg + MOV ES,AX + OR AX,DI + JZ get_alter_map_reg1 + MOV SI,OFFSET map_table + PUSH CS + POP DS + MOV CX,CONTEXT_SIZE/2 + REPZ MOVSW +get_alter_map_reg1: + MOV DI,CS:alter_map_off + MOV AX,CS:alter_map_seg + MOV [BP].di_save,DI + MOV [BP].es_save,AX + MOV BX,[BP].bx_save + xor bl,bl + MOV [BP].bx_save,BX + JMP noerr +;-------------------------------------------------------------------- +; Set alternate map register set +; input +; BL : new alternate map register set number +; ES:DI : pointer to a map register context restore area +; output +; AH : status +;-------------------------------------------------------------------- +set_alter_map_reg: + cli + or bl,bl + jnz set_alter_map_reg1 + mov alter_map_off,di + mov ax,es + mov alter_map_seg,ax + or ax,di + jz set_alter_map_reg2 + push es + pop ds + mov si,di + mov cx,CONTEXT_SIZE/2 + mov ax,ss + mov es,ax + lea di,[bp].f28_map_data + rep movsw + lea di,[bp].f28_map_data + call check_map_data + jc set_alter_map_reg3 + mov si,di + push es + pop ds + mov cx,CONTEXT_SIZE/2 + mov di,offset map_table + push cs + pop es + rep movsw + call set_pages_map +set_alter_map_reg2: + jmp noerr +set_alter_map_reg1: + jmp err9c +set_alter_map_reg3: + jmp erra3 +;------ function 29 ------------------------------------------------- +; Prepare expanded memory hardware for warm boot +;-------------------------------------------------------------------- +func29: + MOV AX,CS + MOV ES,AX + MOV DS,AX + MOV DI,OFFSET map_table ;disable physical pages... + MOV CX,PHYS_PAGES +f291: + MOV [DI].emm_handle2,UNMAP + MOV [DI].log_page_data,0 + ADD DI,SIZE phys_page_struct + loop f291 + call set_pages_map + MOV DI,OFFSET alloc_page_count;clear all... + mov cx,HANDLE_CNT*3 + xor ax,ax + rep stosw + MOV DI,OFFSET handle_name ;clear handles... + MOV CX,HANDLE_CNT*4 + REPZ STOSW + MOV di,OFFSET backup_flags ;v1.01 + mov cx,CONTEXT_SIZE/2 + rep stosw + MOV DI,OFFSET alloc_page ;clear logical page buffer... + MOV CX,PAGE_MAX*2 + dec ax ; set to -1 + REPZ STOSW + MOV byte ptr handle_flag,1 ;set system handle flag... + MOV handle_count,1 ;set active handle count + MOV backup_count,0 ;set backup map count + MOV AX,total_pages + MOV un_alloc_pages,AX ;set unallocate page count + MOV AX,OFFSET alloc_page ;set page buffer pointer + MOV page_ptr,AX + JMP noerr ;exit +;------ function 30 ------------------------------------------------- +; Enable/disable OS/E function set functions +; input +; BX,CX : alternate register set number +; output +; AH : status +; BX,CX : alternate register set number +;-------------------------------------------------------------------- +func30: + sti + dec al + js enable_OSE_func ; 0 + jz disable_OSE_func ; 1 + dec al + jz return_access_key ; 2 + jmp err84 ;error exit + +;-------------------------------------------------------------------- +; Enable OS/E function set +; input +; BX,CX : access_key +; output +; AH : status +; BX,CX : access_key +;-------------------------------------------------------------------- +enable_OSE_func: + CMP OSE_fast,0 ;OS/E fast access flag enable? + JZ enable_OSE_func1 + CMP access_key_h,BX ;compare access key high + JNZ enable_OSE_func2 + CMP access_key_l,CX ;compare access key low + jnz enable_OSE_func2 +enable_OSE_func1: + MOV OSE_flag,0 ;enable OS/E function + MOV OSE_fast,0FFFFH ;set OS/E fast access flag + MOV BX,access_key_h + MOV [BP].bx_save,BX + MOV CX,access_key_l + MOV [BP].cx_save,CX + JMP noerr +enable_OSE_func2: + JMP erra4 +;-------------------------------------------------------------------- +; Disable OS/E function set +; input +; BX,CX : access_key +; output +; AH : status +; BX,CX : access_key +;-------------------------------------------------------------------- +disable_OSE_func: + CMP OSE_fast,0 ;OS/E fast access flag enable? + JZ disable_OSE_func1 + CMP access_key_h,BX ;compare access key high + JNZ enable_OSE_func2 + CMP access_key_l,CX ;compare access key low + jnz enable_OSE_func2 +disable_OSE_func1: + MOV OSE_flag,0FFFFH ;disable OS/E function + MOV OSE_fast,0FFFFH ;set OS/E fast access flag + MOV BX,access_key_h + MOV [BP].bx_save,BX + MOV CX,access_key_l + MOV [BP].cx_save,CX + JMP noerr +;-------------------------------------------------------------------- +; Return access key +; input +; BX,CX : access_key +; output +; AH : status +;-------------------------------------------------------------------- +return_access_key: + CMP OSE_flag,0 ;OS/E flag enable? + jnz enable_OSE_func2 + CMP access_key_h,BX ;compare access key high + jnz enable_OSE_func2 + CMP access_key_l,CX ;compare access key low + jnz enable_OSE_func2 + MOV OSE_flag,0 ;enable OS/E function + MOV OSE_fast,0 ;reset OS/E fast access flag + XOR AX,AX + MOV ES,AX + MOV AX,ES:[46CH] + ADD BX,AX ;make access key... + MOV access_key_h,BX + ADC AX,ES:[46EH] + ADD CX,AX + MOV access_key_l,CX + JMP noerr +;......................................................................... +;-------------------------------------------------------------------- +; \82\EB\E7\A8á«¥\AD\A8\A5 \AC\A0\AAᨬ\A0\ABì­® \A2\AE\A7\AC\AE\A6\AD\AE\A9 \A4\AB\A8\AD\EB \A1\AB\AEç­®\A9 \AF\A5\E0\A5\E1뫪\A8 +; \A2室 +; BL : ⨯ \AF\A0\AC\EF\E2\A8 (0=RAM,1=EMS) +; AX : ᬥ饭\A8e \A1\AB\AE\AA\A0 +; \A2\EB室 +; AX : \A4\AB\A8\AD\A0 \AF\A5\E0\A5\E1뫪\A8 +;-------------------------------------------------------------------- +maxlen PROC NEAR + or bl,bl + jnz max1 + test [bp].direct_move,1 ;\A4\AB\EF ᮢ\AC\A5\E1⨬\AE\A9 \AF\A0\AC\EF\E2\A8... + jnz max2 + neg ax + jmp short max3 +max2: + inc ax +max3: + or ax,ax + jnz max4 + dec ax + ret +max1: + test [bp].direct_move,1 ;\A4\AB\EF EMS... + jnz max5 + sub ax,4000h + neg ax + ret +max5: + inc ax +max4: + ret +maxlen ENDP + +;-------------------------------------------------------------------- +; Check logical page no. +; input +; BX : logical page number in handle +; DX : EMM handle +; output +; AX : logical page number in EMM +; CF = 0 : OK +; CF = 1 : NG +;-------------------------------------------------------------------- +check_log_page PROC NEAR + PUSH CX SI + MOV SI,DX + SHL SI,1 + CMP bl,CS:[SI].alloc_page_count + jnb check_log_page2 + MOV SI,CS:[SI].page_address + MOV AX,BX + SHL AX,1 + ADD SI,AX + MOV AX,CS:[SI] ;get logical no. in EMM + CLC +check_log_page1: + POP SI CX + RET +check_log_page2: + STC + JMP short check_log_page1 +check_log_page ENDP +;-------------------------------------------------------------------- +; Check EMM handle no. +; input +; DX : EMM handle +; output +; CF = 0 : OK +; CF = 1 : NG +;-------------------------------------------------------------------- +check_handle PROC NEAR + PUSH DI + CMP DX,HANDLE_CNT + jnb check_handle1 + MOV DI,DX + SHL DI,1 + cmp byte ptr CS:[DI].handle_flag,0 ;active handle ? + JZ check_handle1 + CLC +check_handle2: + POP DI + RET +check_handle1: + STC + jmp check_handle2 +check_handle ENDP +;-------------------------------------------------------------------- +; Set physical page. +; input +; AL : physical page no. +; BX : logical page no. in EMM (if BX=FFFFH then unmap) +; DX : EMM handle +;-------------------------------------------------------------------- +set_phys_page PROC NEAR + PUSH AX CX DX DI + cbw + MOV DI,OFFSET map_table + MOV CL,SIZE phys_page_struct + MUL CL + ADD DI,AX + PUSH DX + MOV DX,CS:[DI].phys_page_port + MOV AX,BX +; JJP OR AL,80h + OUT DX,AL + POP DX + MOV CS:[DI].emm_handle2,DX ;handle + MOV CS:[DI].log_page_data,AL;logical page no. + POP DI DX CX AX + RET +set_phys_page ENDP +;-------------------------------------------------------------------- +; Change mappable segment address to physical page number. +; input +; AX : mappable segment address +; output +; AX : physical page number +;-------------------------------------------------------------------- +change_seg_page PROC NEAR + PUSH BX CX DI + XOR BX,BX + MOV DI,OFFSET map_table + MOV CX,PHYS_PAGES + CLC ;reset CF +change_seg_page2: + CMP AX,CS:[DI].phys_seg_addr + JZ change_seg_page1 + ADD DI,SIZE phys_page_struct + INC BX + LOOP change_seg_page2 + STC ;set CF +change_seg_page1: + MOV AX,BX + POP DI CX BX + RET +change_seg_page ENDP + +; +; EMS 4.0 Data +; + ALIGN 2 +; +; handle name buffer +; +handle_name LABEL BYTE + DB HANDLE_NAME_SIZE * HANDLE_CNT DUP (0) +; +; f24 Save area +; +f24_data DB SIZE phys_page_struct * 2 dup (0) +; +;-------------------------------------------------------------------- +; EMM driver initilize program +;-------------------------------------------------------------------- +emminit: + PUSH CX DX SI DI ES BP ;Store registers... + PUSH CS + POP DS + XOR AX,AX + MOV ES,AX + MOV SI,19CH + MOV WORD PTR ES:[SI],OFFSET int67;set int67 offset. + MOV ES:[SI+2],CS ;set int67 segment. + CALL getprm ;get parameters + test sysflg,1 + jz emminit1 + call set32 +emminit1: + MOV SI,OFFSET start_msg ;display start messege. + CALL strdsp + CALL ckemsio ;check EMS i/o port + jc errems ;error ? + CALL ramchk ;check EMS memory + jc errems ;error ? + CALL instmsg ;display install message. + XOR AX,AX + MOV ES,AX + MOV AX,ES:[46CH] + ADD BX,AX ;make access key... + MOV access_key_h,BX + ADC AX,ES:[46EH] + ADD BX,AX + MOV access_key_l,BX + XOR DI,DI ;set system handle... + PUSH CS + POP ES + MOV byte ptr es:[DI].handle_flag,1;set system handle active. + INC es:handle_count ;handle count up + MOV AX,OFFSET emminit ;make 4.0 break address... + test sysflg,1 + jz emminit2 + MOV AX,OFFSET func16 ;make 3.2 break address... +emminit2: + ADD AX,0FH + MOV CL,4 + SHR AX,CL + MOV CX,AX + MOV AX,CS + ADD AX,CX + MOV emm_flag,1 ;set EMM install flag. + LDS BX,ptrsav + MOV [BX].brkoff,0 ;break address offset set. + MOV [BX].brkseg,AX ;break address segment set. + JMP short emmint1 +errems: + MOV SI,OFFSET notinst ;display error message + CALL strdsp + MOV emm_flag,0 ;reset EMM install flag. + PUSH CS + POP ES + MOV DI,OFFSET func_table + MOV AX,OFFSET err80 + MOV CX,30 + REPZ STOSW + LDS BX,ptrsav + MOV AX,OFFSET func2 ;set break address offset. + MOV [BX].brkoff,AX ;set break address offset. + MOV [BX].brkseg,CS ;set break address segment. +emmint1: + POP BP ES DI SI DX CX ;Restore registers... + JMP exit ;exit initial program. +;-------------------------------------------------------------------- +; Get CONFIG.SYS parameters. +;-------------------------------------------------------------------- +getprm PROC NEAR + PUSH DS + LES BX,ptrsav + MOV DI,ES:[BX].count + MOV AX,ES:[BX].start + MOV ES,AX + XOR CL,CL +getpr2: + MOV AL,ES:[DI] + CMP AL,CR + JZ getpr4 + CMP AL,'/' ;set page frame address? + jne getpr5 + inc di + MOV AL,ES:[DI] + OR AL,20h ;tolower + CMP AL,'p' ;set page frame address? + JNZ getpr3 + INC DI + MOV AL,ES:[DI] + CMP AL,':' + JNZ getpr5 + INC DI + CALL ascbin2 ;change data ascii -> binary. + JNC getpr8 ;error ? + JMP getpr5 +getpr8: + MOV page_frame_seg,AX + JMP getpr5 +getpr3: + CMP AL,'i' ;set EMS i/o port address? + JNZ getpr6 + INC DI + MOV AL,ES:[DI] + CMP AL,':' + JNZ getpr5 + INC DI + CALL ascbin2 ;change data ascii -> binary. + MOV emsio,AX + JMP getpr5 +getpr6: + CMP AL,'f' ;set EMS i/o port address? + JNZ getpr7 + INC DI + MOV AL,ES:[DI] + CMP AL,':' + JNZ getpr5 + INC DI + CALL ascbin1 ;change data ascii -> binary. + MOV pageofs,al + JMP getpr5 +getpr7: + CMP AL,'q' ;set quiet mode + JNZ getpr1 + OR CL,4 + JMP getpr5 +getpr1: + CMP AL,'n' ;set notest mode + JNZ getpr10 + OR CL,8 + JMP getpr5 +getpr10: + CMP AL,'x' ;set extended memory test + JNZ getpr9 + OR CL,2 + JMP getpr5 +getpr9: + CMP AL,'3' ;set 3.2 mode + JNZ getpr5 + OR CL,1 +getpr5: + INC DI + JMP getpr2 +getpr4: + MOV sysflg,CL ;set system option flag. + POP DS + RET +getprm ENDP +;-------------------------------------------------------------------- +; Display EMM install opening message. +;-------------------------------------------------------------------- +instmsg PROC NEAR + PUSH AX BX CX DI + PUSH CS + POP ES + MOV AX,page_frame_seg + MOV DI,OFFSET segadr + CALL hbinasc + MOV AX,total_pages + MOV DI,OFFSET total_pg + CALL dbinasc + MOV AX,emsio + MOV DI,OFFSET pioadr + CALL hbinasc + MOV AX,total_pages + mov cl,4 + shl ax,cl ; Multiply to 16 + MOV DI,OFFSET totmem + CALL dbinasc + MOV SI,OFFSET install_msg + CALL strdsp + POP DI CX BX AX + RET +instmsg ENDP +;-------------------------------------------------------------------- +; Check EMS i/o port. +; output +; for lo-tech EMS board, we cannot read from the page registers +; hence we just return OK anyway. +; cf = 0 : OK +; cf = 1 : NG +;-------------------------------------------------------------------- +ckemsio PROC NEAR + MOV DX,CS:EMSIO +; JJP IN AL,DX +; JJP CMP AL,255 ;check TRS flag +; JJP JE ckems3 +ckems4: + CLC ;reset CF + RET +ckems3: + MOV SI,OFFSET hard_w_err ;display hardware error messege. + CALL strdsp + STC ;set CF + RET +ckemsio ENDP +;-------------------------------------------------------------------- +; Check expanded memory. +; output +; cf = 0 : OK +; cf = 1 : NG +;-------------------------------------------------------------------- +ramchk PROC NEAR + PUSH AX BX CX DX BP + PUSH CS + POP DS + MOV DI,OFFSET map_table + MOV CX,PHYS_PAGES + MOV BX,emsio + MOV SI,page_frame_seg +ramch14: + MOV [DI].phys_page_port,BX + MOV [DI].log_page_data,0 + MOV [DI].phys_seg_addr,SI + ADD DI,SIZE phys_page_struct + ADD SI,0400H + MOV DX,BX ;disable physical pages --- + MOV AL,DIS_EMS + OUT DX,AL +; JJP ADD BX,4000h + INC BX ; lo-tech cards registers are sequential from base address + LOOP ramch14 + MOV SI,OFFSET pagemsg ;display page test msg.. + CALL strdsp + IN AL,I8042+1 ;logical page test... + OR AL,4 ;system memory parity disable + and al,0feh + OUT I8042+1,AL + MOV DI,OFFSET log_page + MOV DX,emsio + MOV AL,pageofs ;get EMS logical page start no. + xor ah,ah + MOV CX,PAGE_MAX + sub cx,ax + jng ramch16 + mov ah,al + XOR BX,BX +ramch9: + PUSH CX + MOV AL,AH +; JJP OR AL,80h + OUT DX,AL + CALL imgchk ; checks the page is RAM + jc ramch17 + test byte ptr sysflg,8 ;supress memory test + jne ramch2 + call testkb ; check if user press ESC + jnc ramch6 + or byte ptr sysflg,8 ;supress memory test + jmp short ramch2 +ramch6: + test byte ptr sysflg,2 ;long memory test + jne ramch3 + CALL pagetst + jmp short ramch4 +ramch3: + CALL spagetst +ramch4: + jc ramch8 +ramch2: + MOV [DI],NOT_USE + INC BX +ramch17: + ADD DI,LOG_SIZE +ramch8: + POP CX + INC AH + LOOP ramch9 +ramch16: + MOV total_pages,BX + MOV un_alloc_pages,BX + MOV AL,DIS_EMS + OUT DX,AL + IN AL,I8042+1 ;enable system memory parity.. + AND AL,0FBH + or AL,1 + OUT I8042+1,AL + CMP total_pages,0 ;total page zero? + JNZ ramch7 + MOV SI,OFFSET nopage_err ;error message display + CALL strdsp + STC ;set CF + JMP ramch5 +ramch7: + CLC +ramch5: + POP BP DX CX BX AX + RET +ramchk ENDP +;-------------------------------------------------------------------- +; check memory size (1024 KByte) +;-------------------------------------------------------------------- +imgchk PROC NEAR + CLD + PUSH AX CX SI DI DS + PUSH CS ;set ES <- CS.. + POP ES + test ah,3 + jnz imgchk2 + IN AL,I8042+1 + or AL,2 + OUT I8042+1,AL +imgchk2: + MOV AL,AH + CBW + MOV DI,OFFSET tstpage + CALL dbinasc ;change binary -> ascii. + MOV SI,OFFSET tstpage ;display message.. + CALL strdsp + IN AL,I8042+1 + and AL,0fdh + OUT I8042+1,AL + MOV AX,page_frame_seg + MOV ES,AX + MOV ax,chkchr + mov es:[0],ax + cmp es:[0],ax + jne imgch1 + xor ax,ax + mov es:[0],ax + CLC + jmp imgch3 +imgch1: + STC +imgch3: + POP DS DI SI CX AX + RET +imgchk ENDP +;-------------------------------------------------------------------- +; check logical page memory. +; input +; AX : logical page no. +;-------------------------------------------------------------------- +pagetst PROC NEAR + CLD ;reset DF + PUSH AX BX CX DX DI + MOV AX,page_frame_seg ;set page frame address -> ES... + MOV ES,AX + MOV AX,chkchr + XOR DI,DI + MOV CX,2000h + REP STOSW + XOR DI,DI + MOV CX,2000h ;check pattan data... + REPZ SCASW + JZ pagets1 +pagets2: + STC + JMP pagets5 +pagets1: + XOR AX,AX ;clear expand memory... + XOR DI,DI + MOV CX,2000h + REP STOSW + CLC +pagets5: + POP DI DX CX BX AX + RET +pagetst ENDP +;-------------------------------------------------------------------- +spagetst proc near + cld ;reset DF + push ax bx cx di ds + mov ax,page_frame_seg ;set page frame address -> ES... + mov es,ax + mov ds,ax + xor ax,ax + xor di,di + mov cx,2000h + rep stosw ;Fill area with zeros + mov bx,00ffh +; Pass 1 + xor di,di + mov cx,4000h +spagets3: + mov al,[di] + cmp al,bh + jne spagets2 + mov [di],bl + inc di + loop spagets3 +; Pass 2 + xor di,di + mov cx,4000h + xchg bl,bh +spagets4: + mov al,[di] + cmp al,bh + jne spagets2 + mov [di],bl + inc di + loop spagets4 +; Pass 3 + mov di,4000h + dec di + xchg bl,bh +spagets6: + mov al,[di] + cmp al,bh + jne spagets2 + mov [di],bl + dec di + jns spagets6 +; Pass 4 + mov di,4000h + dec di + xchg bl,bh +spagets7: + mov al,[di] + cmp al,bh + jne spagets2 + mov [di],bl + dec di + jns spagets7 + clc +spagets5: + pop ds di cx bx ax + ret +spagets2: + stc + jmp spagets5 +spagetst endp +;-------------------------------------------------------------------- +; Change data BYNARY -> ASCII (DEC) +; input +; AX : binary data +; output +; ES:DI : ascii data (DEC) +;-------------------------------------------------------------------- +dbinasc: + PUSH AX BX CX DX SI + MOV SI,DI + MOV CX,4 + MOV BX,1000 + XOR DX,DX +dbinas1: + DIV BX + OR AL,AL + JNZ dbinas2 + CMP CL,4 + JZ dbinas4 + CMP BYTE PTR [SI],' ' + JNZ dbinas2 +dbinas4: + MOV AL,' ' + CMP CL,1 + JNZ dbinas3 + XOR AL,AL +dbinas2: + ADD AL,'0' +dbinas3: + MOV SI,DI + STOSB + PUSH DX + XOR DX,DX + MOV AX,BX + MOV BX,10 + DIV BX + MOV BX,AX + POP AX + LOOP dbinas1 + POP SI DX CX BX AX + DEC DI + RET +;-------------------------------------------------------------------- +; Change data BYNARY -> ASCII (HEX) +; input +; AX : binary data +; output +; ES:DI : ascii data (HEX) +;-------------------------------------------------------------------- +hbinasc: + PUSH AX BX CX DX SI + MOV SI,DI + MOV CX,4 + MOV BX,1000H + XOR DX,DX +hbinas1: + DIV BX + CMP AL,10 + JC hbinas2 + ADD AL,7 +hbinas2: + ADD AL,'0' +hbinas3: + MOV SI,DI + STOSB + PUSH DX + XOR DX,DX + MOV AX,BX + MOV BX,10H + DIV BX + MOV BX,AX + POP AX + LOOP hbinas1 + POP SI DX CX BX AX + DEC DI + RET +;-------------------------------------------------------------------- +; Change data ASCII (DEC) -> BINARY +; input +; ES:DI = ascii data address (DEC) +; output +; AX = binary data +;-------------------------------------------------------------------- +ascbin1: + PUSH BX CX DX + XOR DL,DL + MOV CX,4 + XOR BX,BX +ascbin11: + MOV AL,ES:[DI] + CMP AL,' ' + JZ ascbin13 + CMP AL,TAB + JNZ ascbin14 +ascbin13: + OR DL,DL + JNZ ascbin12 + INC DI + JMP ascbin11 +ascbin12: + OR DL,DL + JNZ ascbin16 + STC + JMP ascbin15 +ascbin14: + CMP AL,'0' + JC ascbin12 + CMP AL,':' + JNC ascbin12 + MOV DL,1 + SUB AL,'0' + XOR AH,AH + XCHG BX,AX + PUSH DX + MOV DX,10 + MUL DX + ADD BX,AX + POP DX + INC DI + LOOP ascbin11 +ascbin16: + MOV AX,BX + CLC +ascbin15: + POP DX CX BX + RET +;-------------------------------------------------------------------- +; Change data ASCII (HEX) -> BINARY +; input +; ES:DI = ascii data address (HEX) +; output +; AX = binary data +;-------------------------------------------------------------------- +ascbin2: + PUSH BX CX DX + XOR DL,DL + MOV CX,4 + XOR BX,BX +ascbin21: + MOV AL,ES:[DI] + CMP AL,' ' + JZ ascbin23 + CMP AL,TAB + JNZ ascbin24 +ascbin23: + OR DL,DL + JNZ ascbin22 + INC DI + JMP ascbin21 +ascbin22: + OR DL,DL + JNZ ascbin27 + STC + JMP ascbin25 +ascbin24: + CMP AL,'0' + JC ascbin22 + CMP AL,':' + JC ascbin26 + CMP AL,'A' + JC ascbin22 + CMP AL,'G' + JNC ascbin22 + SUB AL,7 +ascbin26: + MOV DL,1 + SUB AL,'0' + XOR AH,AH + XCHG BX,AX + PUSH DX + MOV DX,10H + MUL DX + ADD BX,AX + POP DX + INC DI + LOOP ascbin21 +ascbin27: + MOV AX,BX + CLC +ascbin25: + POP DX CX BX + RET +;-------------------------------------------------------------------- +; STRINGS DISPLAY SUB +; input +; DS:SI : strings datas +;-------------------------------------------------------------------- +strdsp: + test byte ptr cs:sysflg,4 ;supress output + jnz strdsp1 ;when in quet mode + PUSH AX DX ES + PUSH CS + POP ES + MOV DX,SI + MOV AH,9 + INT 21H ;bdos call + POP ES DX AX +strdsp1: + RET +; +; Set EMS 3 mode +; +set32: + mov byte ptr msg_ver,'3' + mov byte ptr msg_ver+2,'2' + mov byte ptr f7_ver,32h + mov byte ptr f_max,4fh + ret +; +; Test ESC from keyboard +; +testkb: + push ax + mov ah,1 + int 16h + jz testkb1 + xor ah,ah + int 16h + cmp al,27 + jne testkb1 + stc + jmp short testkb2 +testkb1: + clc +testkb2: + pop ax + ret +;____________________________________________________________________ +; +; This is "EXE" part of this driver +; +;____________________________________________________________________ +info: + push cs + pop ds + mov si, offset start_msg ; Display title & version + call strdsp + mov si, offset info_msg ; Display switches + call strdsp + mov ax,4c00h ;Exit to DOS + int 21h +;____________________________________________________________________ + +;-------------------------------------------------------------------- +; EMM driver initial routine work data area +;-------------------------------------------------------------------- +start_msg db CR,LF + DB 'LTEMM: Lo-tech EMM Driver for XTMax ' +msg_ver db 'r01' + DB CR,LF,'$' +install_msg label byte +page_msg DB 'Page frame specification: Frame Segment at ' +segadr DB '0000',CR,LF +total_pg DB '0000 pages found on EMS board at ' +pioadr DB '0000',CR,LF + db 'Installation completed - ' +totmem db '0000K RAM Available.',CR,LF,LF,'$' +hard_w_err DB 'No EMS board found.',CR,LF,'$' +nopage_err DB 'No EMS memory found.',CR,LF,'$' +notinst DB 'Installation failed - No EMS available.',CR,LF,LF,'$' +pagemsg DB '0000 Pages testing, Esc bypass test',CR,'$' +tstpage DB '0000',CR,'$' +info_msg db CR,LF + db 'Expanded Memory Manager for the XTMax expansion board.',CR,LF + db CR,LF + db 'Based on Lo-tech EMM Driver for the Lo-tech 2MB EMS board..',CR,LF + db 'Based on original works Copyright (c) 1988, Alex Tsourikov.',CR,LF + db 'All rights reserved.',CR,LF + db CR,LF + db 'http://www.lo-tech.co.uk/wiki/2MB-EMS-Board',CR,LF + db 'Syntax: DEVICE=LTEMM.EXE [/switches]',CR,LF + db CR,LF + db ' /p:nnnn - Page frame address(E000)',CR,LF + db ' /i:nnn - EMS i/o port base address(260)',CR,LF + db ' /h:nnn - Maximal number of handles(64)',CR,LF + db ' /d:nn - Depth of contest saves(5)',CR,LF +; db ' /f:nnn - First page number(0)',CR,LF + db ' /n - Bypass memory test',CR,LF + db ' /x - Perform long memory test',CR,LF + db ' /3 - Use only EMS 3.2 functions',CR,LF + db ' /q - Quiet mode',CR,LF + db CR,LF + db 'Defaults in parentheses.',CR,LF,'$' +pageofs DB 0 ;logical page no. offset data +sysflg DB 0 ;system option flag +chkchr DW 55AAH +code ENDS + END INFO diff --git a/XTMax/Drivers/LTEMM/LTEMM.EXE b/XTMax/Drivers/LTEMM/LTEMM.EXE new file mode 100644 index 0000000..c8d56d4 Binary files /dev/null and b/XTMax/Drivers/LTEMM/LTEMM.EXE differ diff --git a/XTMax/Drivers/LTEMM/LTEMM.INC b/XTMax/Drivers/LTEMM/LTEMM.INC new file mode 100644 index 0000000..21de6f7 --- /dev/null +++ b/XTMax/Drivers/LTEMM/LTEMM.INC @@ -0,0 +1,226 @@ +;***************************************************************** +;* * +;* * +;* EMM/EMS driver program for BOCARAM30 Memory board * +;* * +;* * +;***************************************************************** +; +; ‘âàãªâãà  ä¨§¨ç¥áª®© áâà ­¨æë EMS +; +phys_page_struct STRUC + Emm_Handle2 DW ? ;¤¥áªà¨¯â®à-¢« ¤¥«¥æ áâà ­¨æë + Phys_page_port DW ? ;physical page i/o port address + Phys_Seg_Addr DW ? ;䨧¨ç¥áª¨© ᥣ¬¥­â­ë©  ¤à¥á áâà ­¨æë + Log_Page_Data DB ? ;­®¬¥à «®£¨ç¥áª®© áâà ­¨æë,ª àâ¨à®¢ ­­®© +phys_page_struct ENDS ;­  íâã 䨧¨ç¥áªãî áâà ­¨æã + +handle_page_struct STRUC + emm_handle3 DW ? + page_alloc_to_handle DW ? +handle_page_struct ENDS + +partial_page_map_struct STRUC + mappable_segment_count DW ? + mappable_segment DW 4 DUP (?) +partial_page_map_struct ENDS + +log_to_phys_map_struct STRUC + log_page_number1 DW ? + phys_page_number1 DW ? +log_to_phys_map_struct ENDS + +log_to_seg_map_struct STRUC + log_page_number2 DW ? + mappable_seg_addr DW ? +log_to_seg_map_struct ENDS + +handle_dir_struct STRUC + handle_value DW ? + handle_name1 DB 8 DUP (?) +handle_dir_struct ENDS + +map_and_jump_struct STRUC + target_address1 DD ? + log_phys_map_len DB ? + log_phys_map_ptr DD ? +map_and_jump_struct ENDS + +map_and_call_struct STRUC + target_address2 DD ? + new_page_map_len DB ? + new_page_map_ptr DD ? + old_page_map_len DB ? + old_page_map_ptr DD ? + reserved DW 4 DUP (?) +map_and_call_struct ENDS + +move_info_struct STRUC + region_lenght DD ? + source_type DB ? + source_handle1 DW ? + source_offset DW ? + source_seg_page DW ? + dest_type DB ? + dest_handle1 DW ? + dest_offset DW ? + dest_seg_page DW ? +move_info_struct ENDS + +mappable_phys_page_struct STRUC + phys_page_segment DW ? + phys_page_number2 DW ? +mappable_phys_page_struct ENDS + +hardware_info_struct STRUC + raw_page_size DW ? + alternate_register_sets DW ? + context_save_area_size DW ? + DMA_register_sets DW ? + DMA_channel_operation DW ? +hardware_info_struct ENDS + +HANDLE_CNT EQU 64 ;max handle count +PAGE_MAX EQU 255 ;max logical page count +BACK_MAX EQU 5 ;max mapping data backup count +I8042 EQU 60H ;i8042 i/o port address +TIME_OUT EQU 1000 ; +NOT_USE EQU 0AA55H ;not used logical page code +NON EQU 0FFFFH ;non or bad logical page code +CR EQU 0DH ;Carriage Return code +LF EQU 0AH ;Line Feed code +TAB EQU 09H ;TAB code +; JJP DIS_EMS EQU 0 ;physical page disable data +DIS_EMS EQU 0FFH ;physical page disable data (lo-tech cards) +HANDLE_NAME_SIZE EQU 8 ;EMM handle name byte size +UNMAP EQU 0FFFFH ;unmap code +UNALLOC EQU 0FFFFH ;unallocate code +PUSH_REG EQU 8 * 2 ;push register size +EMMWORK EQU 50 ;EMM driver work area size +RET_SP EQU EMMWORK+PUSH_REG+6+10 ;int67 stack size +PHYS_PAGES EQU 4 ;physical page count +RAW_PAGES EQU 400H ;raw page size (16KB) +CONTEXT_SIZE EQU SIZE phys_page_struct * PHYS_PAGES +ALTER_REGS EQU 0 ;alter map register set count +DMA_REGS EQU 0 ;alter DMA register set count +DMA_CHANNEL EQU 0 ;DMA channel number +VOLATILE EQU 0 ;volatile +NON_VOLATILE EQU 1 ;non volatile +F23_RETSP EQU 10 ; +LOG_SIZE EQU 2 ;logical page flag data size +FLAG_SIZE EQU 2 ;handle flag size + +; +; function 15 struct +; +f15_struct STRUC + DW 8 DUP (?) + f15_map_data DB CONTEXT_SIZE DUP (?) +f15_struct ENDS + +; +; function 16 struct +; +f16_struct STRUC + DW 8 DUP (?) + f16_map_len DW ? + f16_map_data DB CONTEXT_SIZE DUP (?) +f16_struct ENDS + +; +; function 17 struct +; +f17_struct STRUC + DW 8 DUP (?) + f17_ax_save DW ? + f17_map_len DW ? + f17_map_data DB PHYS_PAGES * 4 DUP (?) +f17_struct ENDS + +; +; function 22 struct +; +f22_struct STRUC + DW 8 DUP (?) + f22_ax_save DW ? + f22_target_off DW ? + f22_target_seg DW ? + f22_map_len DW ? + f22_map_data DB PHYS_PAGES * 4 DUP (?) +f22_struct ENDS + +; +; function 23 struct +; +f23_struct STRUC + DW 8 DUP (?) + f23_target_off DW ? + f23_target_seg DW ? + f23_flag DW ? + f23_retoff DW ? + f23_retseg DW ? + f23_ax_save DW ? + f23_new_map_len DW ? + f23_new_map_data DB PHYS_PAGES * 4 DUP (?) + f23_old_map_len DW ? + f23_old_map_data DB PHYS_PAGES * 4 DUP (?) +f23_struct ENDS + +; +; function 24 struct +; +f24_struct STRUC + DW 8 DUP (?) + region_low DW ? + region_high DW ? + source_off DW ? + source_seg DW ? + source_page DW ? + source_ea_low DW ? + source_ea_high DW ? + source_handle2 DW ? + dest_off DW ? + dest_seg DW ? + dest_page DW ? + dest_ea_low DW ? + dest_ea_high DW ? + dest_handle2 DW ? + f24_al_save DB ? + direct_move DB ? + source_type1 db ? + dest_type1 db ? + zero_low DW ? +f24_struct ENDS + +; +; function 28 struct +; +f28_struct STRUC + DW 8 DUP (?) + f28_map_data DB CONTEXT_SIZE DUP (?) +f28_struct ENDS + +; +; register back area struct +; +retreg STRUC + bx_save DW ? ;BX save area + cx_save DW ? ;CX save area + dx_save DW ? ;DX save area + si_save DW ? ;SI save area + di_save DW ? ;DI save area + bp_save DW ? ;BP save area + es_save DW ? ;ES save area + ds_save DW ? ;DS save area +retreg ENDS + +; +; return address struct +; +ret_struct STRUC + DW 8 DUP (?) + DB EMMWORK DUP (?) + ret_offset DW ? ;return offset address + ret_segment DW ? ;return segment address + ret_flag DW ? ;return flags +ret_struct ENDS diff --git a/XTMax/Drivers/LTEMM/LTEMM.MAC b/XTMax/Drivers/LTEMM/LTEMM.MAC new file mode 100644 index 0000000..816e7bc --- /dev/null +++ b/XTMax/Drivers/LTEMM/LTEMM.MAC @@ -0,0 +1,100 @@ +;***************************************************************** +;* * +;* * +;* EMM/EMS driver program for BOCARAM30 Memory board * +;* * +;* * +;***************************************************************** +; Some useful macros ... +;Ž¡¬¥­ ¡ ©â ¬¨ ¬¥¦¤ã SOURCE ¨ DESTINATION +Exbyte MACRO + mov al,[si] + xchg al,es:[di] + mov [si],al + inc si + inc di + ENDM + +;Ž¡¬¥­ á«®¢ ¬¨ ¬¥¦¤ã SOURCE ¨ DESTINATION +Exword MACRO + mov ax,[si] + xchg ax,es:[di] + mov [si],ax + add di,2 + add si,2 + ENDM + +;‚ëç¨á«¥­¨¥  ¡á®«îâ­®£®  ¤à¥á  FAR-㪠§ â¥«ï +;‚室 : 㪠§ â¥«ì ¢ ä®à¬ â¥ ᥣ¬¥­â:ᬥ饭¨¥ +;‚ë室 : DX:AX =  ¡á®«îâ­ë©  ¤à¥á +FarPtrAddress MACRO Segment,Offset + mov dx,Segment + mov ax,Offset + mov bx,dx + mov cl,4 + shl bx,cl + and dx,0F000h + rol dx,cl + add ax,bx + adc dx,0 + ENDM + +;‚ëç¨á«¥­¨¥  ¡á®«îâ­®£®  ¤à¥á  FAR-㪠§ â¥«ï +;‚室 : 㪠§ â¥«ì ᥣ¬¥­â:ᬥ饭¨¥ (DX:AX) +;‚ë室 : DX:AX =  ¡á®«îâ­ë©  ¤à¥á +FarAddress MACRO + mov bx,dx + mov cl,4 + shl bx,cl + and dx,0F000h + rol dx,cl + add ax,bx + adc dx,0 + ENDM + +;‘¤¢¨£ ¢«¥¢® 32-à §à來®£® ç¨á«  (DX:AX) ­  COUNT à § +Shl32 MACRO Count + REPT Count + shl ax,1 + rcl dx,1 + ENDM + ENDM + +;‘¤¢¨£ ¢¯à ¢® 32-à §à來®£® ç¨á«  (DX:AX) ­  COUNT à § +Shr32 MACRO Count + REPT Count + shr dx,1 + rcr ax,1 + ENDM + ENDM + +;‘«®¦¥­¨¥ 32-à §à來ëå ç¨á¥« (DX:AX) + HIGH-LOW +Add32 MACRO High,Low + add ax,Low + adc dx,High + ENDM + +;‚ëç¨â ­¨¥ 32-à §à來ëå ç¨á¥« (DX:AX) - HIGH-LOW +Sub32 MACRO High,Low + sub ax,Low + sbb dx,High + ENDM + +;‡ £à㧪  32-à §à來®£® ç¨á«  ¢ (DX:AX) +Load32 MACRO High,Low + mov dx,High + mov ax,Low + ENDM + +;‡ £à㧪  32-à §à來®£® ç¨á«  ¢ (DX:AX) +FLoad32 MACRO Strt + les ax,dword ptr Strt + mov dx,es + ENDM + +;‘®åà ­¥­¨¥ 32-à §à來®£® ç¨á«  (DX:AX) ¢ HIGH-LOW +Save32 MACRO High,Low + mov High,dx + mov Low,ax + ENDM + diff --git a/XTMax/Drivers/LTEMM/MAKEFILE b/XTMax/Drivers/LTEMM/MAKEFILE new file mode 100644 index 0000000..a991c1c --- /dev/null +++ b/XTMax/Drivers/LTEMM/MAKEFILE @@ -0,0 +1,5 @@ +LTEMM.EXE: LTEMM.O + TLINK LTEMM.O + +LTEMM.O: LTEMM.ASM LTEMM.INC LTEMM.MAC + TASM LTEMM.ASM LTEMM.O diff --git a/XTMax/Drivers/LTEMM/README.TXT b/XTMax/Drivers/LTEMM/README.TXT new file mode 100644 index 0000000..0e1c31d --- /dev/null +++ b/XTMax/Drivers/LTEMM/README.TXT @@ -0,0 +1,38 @@ +************************************************************************* +* * +* EMS 4.0 Driver for Lo-tech 2MB EMS Board, rev.01, Mar-14 * +* * +* http://www.lo-tech.co.uk/wiki/2MB-EMS-Board * +* http://www.lo-tech.co.uk/wiki/LTEMM.EXE * +* * +* This code is TASM source. * +* * +* Based on original works Copyright (c) 1988, Alex Tsourikov. * +* All rights reserved. * +* * +* Original source kindly provided subject to the BSD 3-Clause * +* License: http://opensource.org/licenses/BSD-3-Clause * +* * +* This software, as modified, is provided subject to the terms * +* of use at: * +* * +* http://www.lo-tech.co.uk/wiki/lo-tech.co.uk:General_disclaimer * +* * +* No charge has been made for this software. * +* * +************************************************************************* + +Syntax: DEVICE=LTEMM.EXE [/switches] + /p:nnnn - Page frame address (E000) + /i:nnn - EMS i/o port base address (260) + /h:nnn - Maximal number of handles (64) + /d:nn - Depth of contest saves (5) + /f:nnn - First page number (0) + /n - Bypass memory test + /x - Perform long memory test + /3 - Use only EMS 3.2 functions + /q - Quiet mode + +Defaults in parentheses. This driver has been tested under MS-DOS 6.22. + + diff --git a/XTMax/Drivers/SDPP/.gitignore b/XTMax/Drivers/SDPP/.gitignore new file mode 100644 index 0000000..37ebf5e --- /dev/null +++ b/XTMax/Drivers/SDPP/.gitignore @@ -0,0 +1,3 @@ +*.obj +*.map +log.txt diff --git a/XTMax/Drivers/SDPP/.vscode/tasks.json b/XTMax/Drivers/SDPP/.vscode/tasks.json new file mode 100644 index 0000000..b9c2cd2 --- /dev/null +++ b/XTMax/Drivers/SDPP/.vscode/tasks.json @@ -0,0 +1,20 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Build in DOSBox", + "type": "shell", + "command": "..\\Driver_Build_Tools\\DOSBox\\DOSBox.exe -conf Build.conf", + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [], + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} diff --git a/XTMax/Drivers/SDPP/Build.conf b/XTMax/Drivers/SDPP/Build.conf new file mode 100644 index 0000000..7f94f5e --- /dev/null +++ b/XTMax/Drivers/SDPP/Build.conf @@ -0,0 +1,15 @@ +[autoexec] +@ECHO OFF +CLS +MOUNT C . +MOUNT D ..\Driver_Build_Tools\BCC31 +SET PATH=D:\ +C: +MAKE > LOG.TXT +IF ERRORLEVEL 1 GOTO :ERROR +EXIT +:ERROR +TYPE LOG.TXT +ECHO Log saved to LOG.TXT +PAUSE +EXIT diff --git a/XTMax/Drivers/SDPP/CPRINT.C b/XTMax/Drivers/SDPP/CPRINT.C new file mode 100644 index 0000000..5298494 --- /dev/null +++ b/XTMax/Drivers/SDPP/CPRINT.C @@ -0,0 +1,123 @@ +/* cprint.c */ +/* */ +/* This file contains simple ASCII output routines. These are used */ +/* by the device driver for debugging, and to issue informational */ +/* messages (e.g. while loading). In general the C run time library */ +/* functions probably aren't safe for use withing the context of a */ +/* device driver and should be avoided. */ +/* */ +/* All these routines do their output thru the routine outchr, which */ +/* is defined in DRIVER.ASM. It calls the BIOS INT 10 "dumb TTY" */ +/* output function directly and does not use MSDOS at all. */ +/* */ +/* Copyright (C) 1994 by Robert Armstrong */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT- */ +/* ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */ +/* Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, visit the website of the Free */ +/* Software Foundation, Inc., www.gnu.org. */ + +#include /* NULL, etc... */ +#include /* used only for MK_FP ! */ +#include /* needed for variable argument lists */ + +/* outchr - print a single ASCII character */ +void outchr (char ch) +{ + _DI = _SI = 0; + _AL = ch; _AH = 0xE; _BX = 0; + asm INT 0x10; +} + + +/* outstr - print an ASCIZ string */ +void outstr (char *p) +{ + while (*p != '\0') + outchr (*p++); +} + +/* outdec - print a signed decimal integer */ +void outdec (int val) +{ + if (val < 0) + {outchr('-'); val = -val;} + if (val > 9) + {outdec( val/10 ); val %= 10;} + outchr('0' + val); +} + +/* outhex - print a n digit hex number with leading zeros */ +void outhex (unsigned val, int ndigits) +{ + if (ndigits > 1) + outhex (val >> 4, ndigits-1); + val &= 0xf; + if (val > 9) + outchr('A'+val-10); + else + outchr('0'+val); +} + +/* outhex - print a n digit hex number with leading zeros */ +void outlhex (unsigned long lval) +{ + int i; + for (i=3;i>=0;i--) + outhex(((unsigned char *)&lval)[i],2); +} + + +/* outcrlf - print a carriage return, line feed pair */ +void outcrlf (void) +{ + outchr ('\r'); outchr ('\n'); +} + +/* cprintf */ +/* This routine provides a simple emulation for the printf() function */ +/* using the "safe" console output routines. Only a few escape seq- */ +/* uences are allowed: %d, %x and %s. A width modifier (e.g. %2x) is */ +/* recognized only for %x, and then may only be a single decimal digit. */ +void cdprintf (char near *msg, ...) +{ + va_list ap; char *str; int size, ival; unsigned uval; unsigned long luval; + va_start (ap, msg); + + while (*msg != '\0') { +/*outhex((unsigned) msg, 4); outchr('='); outhex(*msg, 2); outchr(' ');*/ + if (*msg == '%') { + ++msg; size = 0; + if ((*msg >= '0') && (*msg <= '9')) + {size = *msg - '0'; ++msg;} + if (*msg == 'c') { + ival = va_arg(ap, int); outchr(ival&0xff); ++msg; + } else if (*msg == 'd') { + ival = va_arg(ap, int); outdec (ival); ++msg; + } else if (*msg == 'x') { + uval = va_arg(ap, unsigned); ++msg; + outhex (uval, (size > 0) ? size : 4); + } else if (*msg == 'L') { + luval = va_arg(ap, unsigned long); ++msg; + outlhex (luval); + } else if (*msg == 's') { + str = va_arg(ap, char *); outstr (str); ++msg; + } + } else if (*msg == '\n') { + outchr('\r'); outchr('\n'); ++msg; + } else { + outchr(*msg); ++msg; + } + } + + va_end (ap); +} diff --git a/XTMax/Drivers/SDPP/CPRINT.H b/XTMax/Drivers/SDPP/CPRINT.H new file mode 100644 index 0000000..e0c7b22 --- /dev/null +++ b/XTMax/Drivers/SDPP/CPRINT.H @@ -0,0 +1,36 @@ +/* */ +/* This file contains simple ASCII output routines. These are used */ +/* by the device driver for debugging, and to issue informational */ +/* messages (e.g. while loading). In general the C run time library */ +/* functions probably aren't safe for use withing the context of a */ +/* device driver and should be avoided. */ +/* */ +/* All these routines do their output thru the routine outchr, which */ +/* is defined in DRIVER.ASM. It calls the BIOS INT 10 "dumb TTY" */ +/* output function directly and does not use MSDOS at all. */ +/* */ +/* Copyright (C) 1994 by Robert Armstrong */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT- */ +/* ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */ +/* Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, visit the website of the Free */ +/* Software Foundation, Inc., www.gnu.org. */ + +#ifndef _CPRINT_H +#define _CPRINT_H +void outchr (char ch); +void outstr (char *p); +void outdec (int val); +void outhex (unsigned val, int ndigits); +void outcrlf (void); +void cdprintf (char near *msg, ...); +#endif diff --git a/XTMax/Drivers/SDPP/DISKIO.H b/XTMax/Drivers/SDPP/DISKIO.H new file mode 100644 index 0000000..0580725 --- /dev/null +++ b/XTMax/Drivers/SDPP/DISKIO.H @@ -0,0 +1,87 @@ +/*----------------------------------------------------------------------- +/ Low level disk interface modlue include file (C)ChaN, 2013 +/-----------------------------------------------------------------------*/ + +#ifndef _DISKIO_DEFINED +#define _DISKIO_DEFINED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "integer.h" + + +/* Status of Disk Functions */ +typedef BYTE DSTATUS; + +/* Results of Disk Functions */ +typedef enum { + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ +} DRESULT; + +void setportbase(BYTE val); /* set the port base */ + +/*---------------------------------------*/ +/* Prototypes for disk control functions */ +#define DOSFAR far + +DSTATUS disk_initialize (BYTE pdrv); +DSTATUS disk_status (BYTE pdrv); +DRESULT disk_result (BYTE pdrv); +DRESULT disk_read (BYTE pdrv, BYTE DOSFAR * buff, DWORD sector, UINT count); +DRESULT disk_write (BYTE pdrv, const BYTE DOSFAR * buff, DWORD sector, UINT count); +DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void DOSFAR * buff); + + +/* Disk Status Bits (DSTATUS) */ +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ + + +/* Command code for disk_ioctrl fucntion */ + +/* Generic command (used by FatFs) */ +#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */ +#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */ +//#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */ +#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */ +#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */ + +/* Generic command (not used by FatFs) */ +//#define CTRL_POWER 5 /* Get/Set power status */ +//#define CTRL_LOCK 6 /* Lock/Unlock media removal */ +//#define CTRL_EJECT 7 /* Eject media */ +//#define CTRL_FORMAT 8 /* Create physical format on the media */ + +/* MMC/SDC specific ioctl command */ +#define MMC_GET_TYPE 10 /* Get card type */ +#define MMC_GET_CSD 11 /* Get CSD */ +#define MMC_GET_CID 12 /* Get CID */ +#define MMC_GET_OCR 13 /* Get OCR */ +#define MMC_GET_SDSTAT 14 /* Get SD status */ + +/* ATA/CF specific ioctl command */ +#define ATA_GET_REV 20 /* Get F/W revision */ +#define ATA_GET_MODEL 21 /* Get model name */ +#define ATA_GET_SN 22 /* Get serial number */ + + +/* MMC card type flags (MMC_GET_TYPE) */ +#define CT_MMC 0x01 /* MMC ver 3 */ +#define CT_SD1 0x02 /* SD ver 1 */ +#define CT_SD2 0x04 /* SD ver 2 */ +#define CT_SDC (CT_SD1|CT_SD2) /* SD */ +#define CT_BLOCK 0x08 /* Block addressing */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/XTMax/Drivers/SDPP/DRIVER.C b/XTMax/Drivers/SDPP/DRIVER.C new file mode 100644 index 0000000..0e27393 --- /dev/null +++ b/XTMax/Drivers/SDPP/DRIVER.C @@ -0,0 +1,508 @@ +/* driver.c - MSDOS device driver functions */ +/* */ +/* Copyright (C) 1994 by Robert Armstrong */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT- */ +/* ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */ +/* Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, visit the website of the Free */ +/* Software Foundation, Inc., www.gnu.org. */ + + +#include /* NULL, etc... */ +#include /* used only for MK_FP ! */ +#include "standard.h" /* definitions for this project */ +#include "sd.h" /* SD card glue */ +#include "diskio.h" /* SD card library header */ +#include "driver.h" /* MSDOS device driver interface */ +#include "cprint.h" /* Console printing */ + + +#define FORM_FACTOR 8 /* DOS form factor code used for SD */ + + +/* Forward declarations for routines that need it... */ +PRIVATE BOOLEAN parse_options (char far *); +PUBLIC void Initialize (rh_init_t far *); +PUBLIC void far SDDriver (rh_t far *); + + +/* These data structures are exported by the HEADER.ASM module... */ +extern devhdr_t header; /* MSDOS device header for our driver */ +extern bpb_t bpb; /* BIOS Parameter block " " " */ +extern bpbtbl_t bpbtbl; /* BPB table (one for each drive unit) */ + +/* This double word is actually a far pointer to the entry point of */ +/* this module. It's called by the assembly interface whenver DOS needs */ +/* driver action. The second word of the far pointer contains the seg- */ +/* ment address, which is actually computed and written by the assembly */ +/* code. */ +PUBLIC WORD c_driver[2] = {(WORD) &SDDriver, 0}; + +extern unsigned char com_flag; + +/* Local data for this module... */ +BOOLEAN Debug = FALSE; /* TRUE to enable debug (verbose) mode */ +BOOLEAN InitNeeded = TRUE; /* TRUE if we need to (re) initialize */ +WORD RebootVector[2]; /* previous INT 19H vector contents */ +extern DWORD partitionoffset; + +extern BYTE sd_card_check; +extern BYTE portbase; + +BYTE partition_number; + +/* fmemcpy */ +/* This function is equivalent to the C RTL _fmemcpy routine. We have */ +/* to define it here because BPC is unable to generate inline code for */ +/* _fmemcpy (although it can generate equivalent code for memcpy!). */ +void fmemcpy (void far *dst, void far *src, WORD n) +{ + _asm { + les di,dword ptr dst + mov dx,word ptr src+2 + mov si,word ptr src + mov cx,n + push ds + mov ds,dx + rep movsb + pop ds + } +} + +/* fmemset */ +/* This is the equivalent to _fmemset. It is here for exactly the */ +/* same reasons as fmemcpy !!! */ +void fmemset (void far *dst, BYTE c, WORD n) +{ + _asm { + mov al,c + les di,dword ptr dst + mov cx,n + rep stosb + } +} + + +/* Media Check */ +/* DOS calls this function to determine if the tape in the drive has */ +/* been changed. The SD hardware can't determine this (like many */ +/* older 360K floppy drives), and so we always return the "Don't Know" */ +/* response. This works well enough... */ +PUBLIC void MediaCheck (rh_media_check_t far *rh) +{ + if (Debug) cdprintf("SD: media check: unit=%d\n", rh->rh.unit); + rh->media_status = SDMediaCheck(rh->rh.unit) ? -1 : 0; + rh->rh.status = DONE; +} + + +/* Build BPB */ +/* DOS uses this function to build the BIOS parameter block for the */ +/* specified drive. For diskettes, which support different densities */ +/* and formats, the driver actually has to read the BPB from the boot */ +/* sector on the disk. */ +PUBLIC void BuildBPB (rh_get_bpb_t far *rh) +{ + if (Debug) + cdprintf("SD: build BPB: unit=%d\n", rh->rh.unit); + rh->bpb = &bpb; + rh->rh.status = DONE; +} + + +/* Get Parameters */ +/* This routine implements the Get Parameters subfunction of the DOS */ +/* Generic IOCTL call. It gets a pointer to the device paramters block, */ +/* which it then fills in. We do NOT create the track/sector map that */ +/* is defined by recent DOS manuals to be at the end of the block - it */ +/* never seems to be used... */ +PUBLIC void GetParameters (device_params_t far *dp) +{ + dp->form_factor = FORM_FACTOR; dp->attributes = 0; dp->media_type = 0; + dp->cylinders = bpb.total_sectors / (bpb.track_size * bpb.head_count); + fmemcpy(&(dp->bpb), &bpb, sizeof(bpb_t)); +} + +/* dos_error */ +/* This routine will translate a SD error code into an appropriate */ +/* DOS error code. This driver never retries on any error condition. */ +/* For actual tape read/write errors it's pointless because the drive */ +/* will have already tried several times before reporting the failure. */ +/* All the other errors (e.g. write lock, communications failures, etc) */ +/* are not likely to succeed without user intervention, so we go thru */ +/* the usual DOS "Abort, Retry or Ignore" dialog. Communications errors */ +/* are a special situation. In these cases we also set global flag to */ +/* force a controller initialization before the next operation. */ +int dos_error (int status) +{ + switch (status) { + case RES_OK: return 0; + case RES_WRPRT: return WRITE_PROTECT; + case RES_NOTRDY: InitNeeded= TRUE; return NOT_READY; + case RES_ERROR: InitNeeded= TRUE; return BAD_SECTOR; + case RES_PARERR: return CRC_ERROR; + + default: + cdprintf("SD: unknown drive error - status = 0x%2x\n", status); + return GENERAL_FAILURE; + } +} + + +/* drive_init */ +/* This routine should be called before every I/O function. If the */ +/* last I/O operation resulted in a protocol error, then this routine */ +/* will re-initialize the drive and the communications. If the drive */ +/* still won't talk to us, then it will set a general failure code in */ +/* the request header and return FALSE. */ +BOOLEAN drive_init (rh_t far *rh) +{ + if (!InitNeeded) return TRUE; + if (!SDInitialize(rh->unit, partition_number, &bpb)) { + if (Debug) cdprintf("SD: drive failed to initialize\n"); + rh->status = DONE | ERROR | GENERAL_FAILURE; + return FALSE; + } + InitNeeded = FALSE; + if (Debug) cdprintf("SD: drive initialized\n"); + return TRUE; +} + + +/* Read Data */ +PUBLIC void ReadBlock (rh_io_t far *rh) +{ + DWORD lbn; + WORD count; int status; BYTE far *dta; + WORD sendct; + if (Debug) + cdprintf("SD: read block: unit=%d, start=%d, count=%d, dta=%4x:%4x\n", + rh->rh.unit, rh->start, rh->count, FP_SEG(rh->dta), FP_OFF(rh->dta)); + if (!drive_init ((rh_t far *) rh)) return; + count = rh->count, lbn = rh->start, dta = rh->dta; + lbn = (rh->start == 0xFFFF) ? rh->longstart : rh->start; + while (count > 0) { + sendct = (count > 16) ? 16 : count; + status = SDRead(rh->rh.unit, lbn, dta, sendct); + if (status != RES_OK) { + if (Debug) cdprintf("SD: read error - status=%d\n", status); + fmemset(dta, 0, BLOCKSIZE); + rh->rh.status = DONE | ERROR | dos_error(status); + return; + } + lbn += sendct; + count -= sendct; + dta += (sendct*BLOCKSIZE); + } + rh->rh.status = DONE; +} + + +/* Write Data */ +/* Write Data with Verification */ +PUBLIC void WriteBlock (rh_io_t far *rh, BOOLEAN verify) +{ + DWORD lbn; + WORD count; int status; BYTE far *dta; + WORD sendct; + if (Debug) + cdprintf("SD: write block: unit=%d, start=%d, count=%d, dta=%4x:%4x\n", + rh->rh.unit, rh->start, rh->count, FP_SEG(rh->dta), FP_OFF(rh->dta)); + if (!drive_init ((rh_t far *) rh)) return; + count = rh->count, dta = rh->dta; + lbn = (rh->start == 0xFFFF) ? rh->longstart : rh->start; + while (count > 0) { + sendct = (count > 16) ? 16 : count; + status = SDWrite(rh->rh.unit, lbn, dta, sendct); + if (status != RES_OK) { + if (Debug) cdprintf("SD: write error - status=%d\n", status); + rh->rh.status = DONE | ERROR | dos_error(status); + return; + } + lbn += sendct; + count -= sendct; + dta += (sendct*BLOCKSIZE); + } + rh->rh.status = DONE; +} + + +/* Generic IOCTL */ +/* The generic IOCTL functions are used by DOS programs to determine */ +/* the device geometry, and especially by the FORMAT program to init- */ +/* ialize new media. The DOS format program requires us to implement */ +/* these three generic IOCTL functions: */ + +PUBLIC void GenericIOCTL (rh_generic_ioctl_t far *rh) +{ + if (Debug) + cdprintf("SD: generic IOCTL: unit=%d, major=0x%2x, minor=0x%2x, data=%4x:%4x\n", + rh->rh.unit, rh->major, rh->minor, FP_SEG(rh->packet), FP_OFF(rh->packet)); + + if (rh->major == DISK_DEVICE) + switch (rh->minor) { + case GET_PARAMETERS: GetParameters ((device_params_t far *) rh->packet); + rh->rh.status = DONE; + return; + case GET_ACCESS: ((access_flag_t far *) (rh->packet))->allowed = 1; + rh->rh.status = DONE; + return; + case SET_MEDIA_ID: + case SET_ACCESS: + case SET_PARAMETERS: + case FORMAT_TRACK: + rh->rh.status = DONE; + return; + case GET_MEDIA_ID: + default: ; + } + cdprintf("SD: unimplemented IOCTL - unit=%d, major=0x%2x, minor=0x%2x\n", + rh->rh.unit, rh->major, rh->minor); + rh->rh.status = DONE | ERROR | UNKNOWN_COMMAND; +} + + +/* Generic IOCTL Query */ +/* DOS programs can use this function to determine which generic */ +/* IOCTL functions a device supports. The query IOCTL driver call will */ +/* succeed for any function the driver supports, and fail for others. */ +/* Nothing actually happens - just a test for success or failure. */ +PUBLIC void IOCTLQuery (rh_generic_ioctl_t far *rh) +{ + if (Debug) + cdprintf("SD: generic IOCTL query: unit=%d, major=0x%2x, minor=0x%2x\n", + rh->rh.unit, rh->major, rh->minor); + if (rh->major == DISK_DEVICE) + switch (rh->minor) { + case GET_ACCESS: + case SET_ACCESS: + case SET_MEDIA_ID: + case GET_PARAMETERS: + case SET_PARAMETERS: + case FORMAT_TRACK: rh->rh.status = DONE; + return; + default: + break; + } + rh->rh.status = DONE | ERROR | UNKNOWN_COMMAND; +} + + +/* SDDriver */ +/* This procedure is called by the DRIVER.ASM interface module when */ +/* MSDOS calls the driver INTERRUPT routine, and the C code is expected */ +/* to define it. Note that the STRATEGY call is handled completely */ +/* inside DRIVER.ASM and the address of the request header block is */ +/* passed to the C interrupt routine as a parameter. */ +PUBLIC void far SDDriver (rh_t far *rh) +{ +/* + if (Debug) + cdprintf("SD: request at %4x:%4x, command=%d, length=%d\n", + FP_SEG(rh), FP_OFF(rh), rh->command, rh->length); +*/ + switch (rh->command) { + case INITIALIZATION: Initialize ((rh_init_t far *) rh); break; + case MEDIA_CHECK: MediaCheck ((rh_media_check_t far *) rh); break; + case GET_BPB: BuildBPB ((rh_get_bpb_t far *) rh); break; + case INPUT: ReadBlock ((rh_io_t far *) rh); break; + case OUTPUT: WriteBlock ((rh_io_t far *) rh, FALSE); break; + case OUTPUT_VERIFY: WriteBlock ((rh_io_t far *) rh, TRUE); break; + case GENERIC_IOCTL: GenericIOCTL ((rh_generic_ioctl_t far *) rh); break; + case IOCTL_QUERY: IOCTLQuery ((rh_generic_ioctl_t far *) rh); break; + + case GET_LOGICAL: + case SET_LOGICAL: rh->status = DONE; break; + + default: + cdprintf("SD: unimplemented driver request - command=%d, length=%d\n", + rh->command, rh->length); + rh->status = DONE | ERROR | UNKNOWN_COMMAND; + } +} + + +PUBLIC void Shutdown (void) +{ + long i; + cdprintf("SD: Shutdown\n"); + for (i=0; i <100000; ++i); + /* SDClose(); */ + JMPVECTOR(RebootVector); +} + + +/* WARNING!! WARNING!! WARNING!! WARNING!! WARNING!! WARNING!! */ +/* */ +/* All code following this point in the file is discarded after the */ +/* driver initialization. Make absolutely sure that no routine above */ +/* this line calls any routine below it!! */ +/* */ +/* WARNING!! WARNING!! WARNING!! WARNING!! WARNING!! WARNING!! */ + + +/* Driver Initialization */ +/* DOS calls this function immediately after the driver is loaded and */ +/* expects it to perform whatever initialization is required. Since */ +/* this function can never be called again, it's customary to discard */ +/* the memory allocated to this routine and any others that are used */ +/* only at initialization. This allows us to economize a little on the */ +/* amount of memory used. */ +/* */ +/* This routine's basic function is to initialize the serial port, go */ +/* and make contact with the SD card, and then return a table of BPBs to */ +/* DOS. If we can't communicate with the drive, then the entire driver */ +/* is unloaded from memory. */ +PUBLIC void Initialize (rh_init_t far *rh) +{ + WORD brkadr, reboot[2]; int status, i; + + /* The version number is sneakily stored in the device header! */ + cdprintf("SD Card driver for XTMax\n based on SD pport device driver V%c.%c (C) 2014 by Dan Marks\n based on TU58 by Robert Armstrong\n", + header.name[6], header.name[7]); + + /* Parse the options from the CONFIG.SYS file, if any... */ + if (!parse_options((char far *) rh->bpbtbl)) { + cdprintf("SD: bad options in CONFIG.SYS\n"); + goto unload2; + } + + /* Calculate the size of this driver by using the address of this */ + /* routine. Note that C will return an offset for &Initialize which */ + /* is relative to the _TEXT segment. We have to adjust this by adding */ + /* the offset from DGROUP. See HEADER.ASM for a memory layout. */ + brkadr = ((WORD) &Initialize) + ((_CS - _DS) << 4); + rh->brkadr = MK_FP(_DS, brkadr); + if (Debug) + cdprintf("SD: CS=%4x, DS=%4x, SS=%4x, SP=%4x, break=%4x\n", + _CS, _DS, _SS, _SP, brkadr); + +/* Try to make contact with the drive... */ + if (Debug) cdprintf("SD: initializing drive\n"); + if (!SDInitialize(rh->rh.unit, partition_number, &bpb)) { + cdprintf("SD: drive not connected or not powered\n"); + goto unload1; + } + cdprintf("SD: rh = %4x:%4x\n", FP_SEG(rh), FP_OFF(rh)); + + reboot[0] = ((WORD) &reboot) + ((_CS - _DS) << 4); + reboot[1] = _CS; + GETVECTOR(0x19, RebootVector); + SETVECTOR(0x19, reboot); + if (Debug) + cdprintf("SD: reboot vector = %4x:%4x, old vector = %4x, %4x\n", + reboot[1], reboot[0], RebootVector[1], RebootVector[0]); + + /* All is well. Tell DOS how many units and the BPBs... */ + cdprintf("SD initialized on DOS drive %c\n", + rh->drive+'A'); + rh->nunits = 1; rh->bpbtbl = &bpbtbl; + rh->rh.status = DONE; + + if (Debug) + { + cdprintf("SD: BPB data:\n"); + cdprintf("Sector Size: %d ", bpb.sector_size); + cdprintf("Allocation unit: %d\n", bpb.allocation_unit); + cdprintf("Reserved sectors: %d ", bpb.reserved_sectors); + cdprintf("Fat Count: %d\n", bpb.fat_count); + cdprintf("Directory size: %d ", bpb.directory_size); + cdprintf("Total sectors: %d\n", bpb.total_sectors); + cdprintf("Media descriptor: %x ", bpb.media_descriptor); + cdprintf("Fat sectors: %d\n", bpb.fat_sectors); + cdprintf("Track size: %d ", bpb.track_size); + cdprintf("Head count: %d\n", bpb.head_count); + cdprintf("Hidden sectors: %d ", bpb.hidden_sectors); + cdprintf("Sector Ct 32 hex: %L\n", bpb.sector_count); + cdprintf("Partition offset: %L\n", partition_offset); + } + return; + + /* We get here if there are any errors in initialization. In that */ + /* case we can unload this driver completely from memory by setting */ + /* (1) the break address to the starting address, (2) the number of */ + /* units to 0, and (3) the error flag. */ +unload1: + { }; +unload2: + rh->brkadr = MK_FP(_DS, 0); rh->nunits = 0; rh->rh.status = ERROR; +} + +/* iseol - return TRUE if ch is any end of line character */ +PRIVATE BOOLEAN iseol (char ch) +{ return ch=='\0' || ch=='\r' || ch=='\n'; } + +/* spanwhite - skip any white space characters in the string */ +PRIVATE char far *spanwhite (char far *p) +{ while (*p==' ' || *p=='\t') ++p; return p; } + +/* option_value */ +/* This routine will parse the "=nnn" part of an option. It should */ +/* be called with a text pointer to what we expect to be the '=' char- */ +/* acter. If all is well, it will return the binary value of the arg- */ +/* ument and a pointer to the first non-numeric character. If there is */ +/* a syntax error, then it will return NULL. */ +PRIVATE char far *option_value (char far *p, WORD *v) +{ + BOOLEAN null = TRUE; + if (*p++ != '=') return NULL; + for (*v=0; *p>='0' && *p<='9'; ++p) + *v = (*v * 10) + (*p - '0'), null = FALSE; + return null ? NULL : p; +} + +/* parse_options */ +/* This routine will parse our line from CONFIG.SYS and extract the */ +/* driver options from it. The routine returns TRUE if it parsed the */ +/* line successfully, and FALSE if there are any problems. The pointer */ +/* to CONFIG.SYS that DOS gives us actually points at the first char- */ +/* acter after "DEVICE=", so we have to first skip over our own file */ +/* name by searching for a blank. All the option values are stored in */ +/* global variables (e.g. DrivePort, DriveBaud, etc). */ +PRIVATE BOOLEAN parse_options (char far *p) +{ + WORD temp; + while (*p!=' ' && *p!='\t' && !iseol(*p)) ++p; + p = spanwhite(p); + while (!iseol(*p)) { + p = spanwhite(p); + if (*p++ != '/') return FALSE; + switch (*p++) { + case 'd', 'D': + Debug = TRUE; + break; + case 'k', 'K': + sd_card_check = 1; + break; + case 'p', 'P': + if ((p=option_value(p,&temp)) == NULL) return FALSE; + if ((temp < 1) || (temp > 4)) + cdprintf("SD: Invalid partition number %x\n",temp); + else + partition_number = temp; + break; + case 'b', 'B': + if ((p=option_value(p,&temp)) == NULL) return FALSE; + if ((temp < 1) || (temp > 5)) + cdprintf("SD: Invalid port base index %x\n",temp); + else + portbase = temp; + break; + default: + return FALSE; + } + p = spanwhite(p); + } + return TRUE; +} + + diff --git a/XTMax/Drivers/SDPP/DRIVER.H b/XTMax/Drivers/SDPP/DRIVER.H new file mode 100644 index 0000000..96f7ed7 --- /dev/null +++ b/XTMax/Drivers/SDPP/DRIVER.H @@ -0,0 +1,232 @@ +/* driver.h - MSDOS commands for a device driver.... */ +/* */ +/* Copyright (C) 1994 by Robert Armstrong */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT- */ +/* ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */ +/* Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, visit the website of the Free */ +/* Software Foundation, Inc., www.gnu.org. */ + +#ifndef _DRIVER_H +#define _DRIVER_H + + +/* NOTE: B implies block device, C implies a character device. */ +/* n.n+ implies DOS version n.n or later only! */ +#define INITIALIZATION 0 /* (BC) initialize driver */ +#define MEDIA_CHECK 1 /* (B) query media changed */ +#define GET_BPB 2 /* (B) BIOS parameter block */ +#define IOCTL_INPUT 3 /* (BC) read IO control data */ +#define INPUT 4 /* (BC) read data */ +#define ND_INPUT 5 /* (C) non-destructive input */ +#define INPUT_STATUS 6 /* (C) query data available */ +#define INPUT_FLUSH 7 /* (C) flush input buffers */ +#define OUTPUT 8 /* (BC) write data */ +#define OUTPUT_VERIFY 9 /* (BC) write data with verify */ +#define OUTPUT_STATUS 10 /* (C) query output busy */ +#define OUTPUT_FLUSH 11 /* (C) flush output buffers */ +#define IOCTL_OUTPUT 12 /* (BC) write IO control data */ +#define DEVICE_OPEN 13 /* (BC) (3.0+) device is to be opened */ +#define DEVICE_CLOSE 14 /* (BC) (3.0+) " " " " closed */ +#define REMOVABLE_MEDIA 15 /* (B) (3.0+) query removable media */ +#define OUTPUT_BUSY 16 /* (C) (3.0+) output data until busy */ +#define GENERIC_IOCTL 19 /* (B) (3.2+) */ +#define GET_LOGICAL 23 /* (BC) (3.2+) */ +#define SET_LOGICAL 24 /* (BC) (3.2+) */ +#define IOCTL_QUERY 25 /* (BC) (5.0+) */ + +/* Flag bits for the request header status word... */ +#define ERROR 0x8000 /* indicates any error condition */ +#define BUSY 0x0200 /* prevents further operations */ +#define DONE 0x0100 /* set on request completion */ + +/* Error codes that may be returned by a device driver... */ +#define WRITE_PROTECT 0x00 /* diskette is write protected */ +#define UNKNOWN_UNIT 0x01 /* unit number does not exist */ +#define NOT_READY 0x02 /* device is not ready */ +#define UNKNOWN_COMMAND 0x03 /* unknown command code */ +#define CRC_ERROR 0x04 /* data check (CRC) error */ +#define HDR_LEN_ERROR 0x05 /* bad request header length */ +#define SEEK_ERROR 0x06 /* seek failure */ +#define UNKNOWN_MEDIA 0x07 /* unknown media (e.g. wrong density) */ +#define BAD_SECTOR 0x08 /* sector not found */ +#define NO_PAPER 0x09 /* printer out of paper */ +#define WRITE_FAULT 0x0A /* write failure */ +#define READ_FAULT 0x0B /* read failure */ +#define GENERAL_FAILURE 0x0C /* general failure */ +#define MEDIA_CHANGED 0x0F /* invalid diskette change */ + +/* Values associated with function 19 - Generic IOCTL... */ +#define SERIAL_DEVICE 0x01 /* device category: any serial device */ +#define CONSOLE_DEVICE 0x03 /* " " : console (display) */ +#define PARALLEL_DEVICE 0x05 /* " " : parallel printer */ +#define DISK_DEVICE 0x08 /* " " : any disk (block) */ +#define SET_PARAMETERS 0x40 /* disk device: set device parameters */ +#define GET_PARAMETERS 0x60 /* " " : get " " " */ +#define WRITE_TRACK 0x41 /* " " : write one track */ +#define READ_TRACK 0x61 /* " " : read " " */ +#define FORMAT_TRACK 0x42 /* " " : format " " */ +#define VERIFY_TRACK 0x62 /* " " : verify " " */ +#define SET_MEDIA_ID 0x46 /* " " : set media id byte */ +#define GET_MEDIA_ID 0x66 /* " " : get " " " */ +#define SENSE_MEDIA 0x68 /* " " : sense media type */ +#define SET_ACCESS 0x67 /* " " : set access allowed flag */ +#define GET_ACCESS 0x47 /* " " : get " " " */ + +struct _devhdr { /* Device header structure... */ + struct _devhdr far *next; /* address of the next device */ + WORD attribute; /* device attribute word */ + void (near *strtgy) (void); /* strategy routine address */ + void (near *intrpt) (void); /* interrupt " " */ + BYTE name[8]; /* device name (blank filled!) */ +}; +typedef struct _devhdr devhdr_t; + +struct _bpb { /* BIOS Parameter block structure... */ + WORD sector_size; /* sector size, in bytes */ + BYTE allocation_unit; /* allocation unit size */ + WORD reserved_sectors; /* number of reserved (boot) sectors */ + BYTE fat_count; /* number of FATs on disk */ + WORD directory_size; /* root directory size, in files */ + WORD total_sectors; /* device size, in sectors */ + BYTE media_descriptor; /* media descriptor code from the BIOS */ + WORD fat_sectors; /* number of sectors per FAT */ + WORD track_size; /* track size, in sectors */ + WORD head_count; /* number of heads */ + LONG hidden_sectors; /* offset of this hard disk partition */ + /* The following device size is used only for disks > 32Mb. In that */ + /* case, the total_sectors field should be zero! */ + LONG sector_count; /* device size, in sectors */ +}; +typedef struct _bpb bpb_t; + +struct _rhfixed { /* Fixed preamble for every request... */ + BYTE length; /* length of the header, in bytes */ + BYTE unit; /* physical unit number requested */ + BYTE command; /* device driver command code */ + WORD status; /* status returned by the driver */ + BYTE reserved[8]; /* reserved (unused) bytes */ +}; +typedef struct _rhfixed rh_t; + +/* NOTE: count is in _bytes_ for character type device drivers, and */ +/* in _sectors_ for block type drivers!! */ + +typedef near * (bpbtbl_t[]); +struct _rh_init { /* INITIALIZATION(0) */ + rh_t rh; /* fixed portion of the header */ + BYTE nunits; /* number of units supported by driver */ + BYTE far *brkadr; /* break address (memory used) */ + bpbtbl_t far *bpbtbl; /* pointer to array of BPBs */ + BYTE drive; /* first available drive number */ +}; +typedef struct _rh_init rh_init_t; + +struct _rh_media_check { /* MEDIA_CHECK(1) */ + rh_t rh; /* fixed portion of the request */ + BYTE media_type; /* media descriptor byte from BIOS */ + BYTE media_status; /* new media status flags */ + BYTE far *volume_id; /* pointer to volume ID string */ +}; +typedef struct _rh_media_check rh_media_check_t; + +struct _rh_get_bpb { /* GET_BPB(2) */ + rh_t rh; /* fixed portion of the request */ + BYTE media_type; /* media descriptor byte from BIOS */ + BYTE far *dta; /* address for data transfer */ + bpb_t far *bpb; /* pointer to the BPB */ +}; +typedef struct _rh_get_bpb rh_get_bpb_t; + +struct _rh_ioctl { /* IOCTL_INPUT(3), IOCTL_OUTPUT(12) */ + rh_t rh; /* fixed portion of the request */ + BYTE media_type; /* media descriptor byte from BIOS */ + BYTE far *dta; /* address for data transfer */ + WORD count; /* transfer count (bytes or sectors) */ + WORD start; /* starting sector number */ +}; +typedef struct _rh_ioctl rh_ioctl_t; + +struct _rh_io { /* INPUT(4),OUTPUT(8),OUTPUT_VERIFY(9) */ + rh_t rh; /* fixed portion of the request */ + BYTE media_type; /* media descriptor byte from BIOS */ + BYTE far *dta; /* address for data transfer */ + WORD count; /* transfer count (bytes or sectors) */ + WORD start; /* starting sector number */ + BYTE far *volume_id; /* address of volume ID string */ + DWORD longstart; /* long start for lba */ +}; +typedef struct _rh_io rh_io_t; + +struct _rh_ndinput { /* ND_INPUT(5) */ + rh_t rh; /* fixed portion of the request */ + BYTE ch; /* next input character (returned) */ +}; +typedef struct _rh_ndinput rh_ndinput_t; + +/* INPUT_STATUS(6) has only a request header... */ +/* INPUT_FLUSH(7) " " " " " ... */ +/* OUTPUT_STATUS(10) " " " " " ... */ +/* OUTPUT_FLUSH(11) " " " " " ... */ +/* DEVICE_OPEN(13) " " " " " ... */ +/* DEVICE_CLOSE(14) " " " " " ... */ +/* REMOVABLE_MEDIA(15) " " " " " ... */ + +struct _rh_output_busy { /* OUTPUT_BUSY(16) */ + rh_t rh; /* fixed portion of the request */ + BYTE media_type; /* media descriptor byte from BIOS */ + BYTE far *dta; /* address for data transfer */ + WORD count; /* transfer count (bytes or sectors) */ +}; +typedef struct _rh_output_busy rh_output_busy_t; + +struct _rh_generic_ioctl { /* GENERIC_IOCTL(19), IOCTL_QUERY(25) */ + rh_t rh; /* fixed portion of the request */ + BYTE major, minor; /* function code - major and minor */ + WORD si, di; /* caller's SI and DI registers */ + BYTE far *packet; /* address of IOCTL data packet */ +}; +typedef struct _rh_generic_ioctl rh_generic_ioctl_t; + +struct _rh_logical { /* GET_LOGICAL(23), SET_LOGICAL(24) */ + rh_t rh; /* fixed portion of the request */ + BYTE io; /* unit code or last device */ + BYTE command; /* command code */ + WORD status; /* resulting status */ + LONG reserved; /* reserved (unused) */ +}; +typedef struct _rh_logical rh_logical_t; + +struct _device_params { /* Generic IOCTL, Get/Set Parameters */ + BYTE special; /* special functions and flags */ + BYTE form_factor; /* device (not media!) form factor */ + WORD attributes; /* physical drive attributes */ + WORD cylinders; /* number of cylinders */ + BYTE media_type; /* media type (not the media id!) */ + bpb_t bpb; /* the entire BIOS parameter block! */ + WORD layout[]; /* track layout map */ +}; +typedef struct _device_params device_params_t; + +struct _access_flag { /* Generic IOCTL Get/Set access allowed */ + BYTE special; /* special functions and flags */ + BYTE allowed; /* non-zero if access is allowed */ +}; +typedef struct _access_flag access_flag_t; + +struct _media_type { /* Generic IOCTL Get media type */ + BYTE default_media; /* 1 for default media type */ + BYTE form_factor; /* media (not device!) form factor */ +}; +typedef struct _media_type media_type_t; + +#endif diff --git a/XTMax/Drivers/SDPP/HEADER.ASM b/XTMax/Drivers/SDPP/HEADER.ASM new file mode 100644 index 0000000..585c20e --- /dev/null +++ b/XTMax/Drivers/SDPP/HEADER.ASM @@ -0,0 +1,247 @@ +PAGE 60, 132 + TITLE HEADER - Interface for C Device Drivers + SUBTTL Bob Armstrong [23-Jul-94] + + + +; header.asm - MSDOS device driver header... +; +; Copyright (C) 1994 by Robert Armstrong +; +; This program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT- +; ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +; Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, visit the website of the Free +; Software Foundation, Inc., www.gnu.org. + + +; This module receives the DOS device driver calls (there are only two!) +; and sets up an environment suitable for executing C code. The original +; DOS device driver request is then handed off to the C code. +; +; There are two requirements that drive the memory layout of a device +; driver: (1) DOS requires the device header to be the first thing in the +; memory image, and (2) it is desirable to free the memory allocated to +; startup code once the driver has been initialized. These requirements +; force a memory layout like this diagram: +; +; DS, SS -> +----------------------+ <- driver load address +; | | +; | (device header) | +; | | +; \ _DATA \ +; | | +; |----------------------| +; | | +; \ _BSS \ +; | | +; | (stack) | <- C language stack +; | | +; CS -> |----------------------| +; | | +; \ _TEXT \ +; | | <- driver break address +; | | +; \ (startup code) \ +; | | +; +----------------------+ +; +; This is very similar to the TINY (.COM file) model _except_ that the +; code is at the end of the memory image rather than the start. This +; turns out to be a major problem because the code generated by TURBO +; assumes that the CS register contains the start of the _TEXT segment +; and NOT the DGROUP. This is contrary to the documentation in the +; Borland manual and _I_ think it's a bug. Note that this bug is +; asymptomatic in .COM files because the _TEXT segment is normally the +; first thing in the DGROUP. +; +; To get around this problem we use the SMALL model (i.e. CS != DS). +; Trouble is, when this driver is loaded the only thing we know is the +; address of the start of the driver and that's in the CS register. +; This means that we have to calculate an appropriate CS value to use +; in the C code. +; +; Another unrelated issue is the stack size. The stack DOS uses when +; a driver is called has room for about 20 PUSHes. This isn't enough +; for any serious C code, so we only use the DOS stack to save all the +; registers. After that we switch to our own stack, which is located +; in the _BSS segment. Of course we have to put the DOS stack pointer +; back before returning. +; +; In order to ensure that the device header appears first in the load +; image it must be defined in this module. We also define the BIOS +; Parameter Block (BPB) and the table of BPB pointers in this module. +; These things are unfortunate because those parts of this file must be +; modified for each different driver. +; +; The only interface between this module and the C code is a single +; far pointer which must be exported by the C code. This pointer would +; be declared as: +; +; void (far *c_driver) (rh_t far *); +; +; The offset part (first word!) of this pointer must be initialized at +; link time with the offset (relative to _TEXT) of the routine that +; will handle DOS driver calls. The segment part of this pointer is +; filled in by this module with the CS value we compute before the +; first call. The C driver routine is passed a far pointer to the +; DOS request header. Everything else is up to the C code. +; +; Bob Armstrong [22-July-1994] + + .8086 + +; This is the size of the new stack we create for the C code... +STACKSIZE EQU 256 ; use whatever seems appropriate... + + +; This DGROUP, and the order the segments appear in this module, will +; force the load order to be as described above! +DGROUP GROUP _DATA, _BSS, _TEXT + + +; The _DATA segment (initialized data) for this module contains the +; MSDOS device header and the BIOS parameter blocks... +_DATA SEGMENT WORD PUBLIC 'DATA' + PUBLIC _header, _bpb, _bpbtbl + +; Header attribute bits for block devices: +; +; 0002H (B1) - 32 bit sector addresses +; 0040H (B6) - Generic IOCTL, Get/Set logical device +; 0080H (B7) - IOCTL Query +; 0800H (B11) - Open/Close device, Removable media +; 2000H (B13) - IBM format +; 4000H (B14) - IOCTL read/write +; 8000H (B15) - zero for block device! + +; The DOS device header... +_header DD -1 ; link to the next device + DW 00C0H ; block device, non-IBM format, generic IOCTL + DW DGROUP:STRATEGY ; address of the strategy routine + DW DGROUP:INTERRUPT; " " " interrupt " + DB 1 ; number of drives + DB 'SDCDv11' ; DOS doesn't really use these bytes + +; The geometry (sectors/track, tracks/cylinder) defined in the BPB is rather +; arbitrary in the case of the TU58, but there are things to watch out for. +; First, the DOS FORMAT program has a bug which causes it to crash or worse +; yet, exit silently without doing anything for devices with large numbers of +; sectors per track. Experiments show that 64 sectors/track is safe (at least +; for DOS v5) but 128 is not. Second, the DRIVER.C module must calculate the +; number of cylinders by cylinders = device_size / (sectors * heads). This +; value must always come out to an integer. + +; The BIOS Parameter Block... +_bpb DW 512 ; sector size + DB 1 ; cluster size + DW 1 ; number of reserved sectors + DB 2 ; number of FAT copies + DW 48 ; number of files in root directory + DW 512 ; total number of sectors + DB 0F0H ; media descriptor + DW 2 ; number of sectors per FAT + DW 64 ; sectors per track + DW 2 ; number of heads + DD 0 ; number of hidden sectors + DD 0 ; large sector count + +; This table contains one BPB pointer for each physical drive... +_bpbtbl DW DGROUP:_bpb ; the BPB for unit 0 +; DW DGROUP:_bpb ; " " " " 1 + +; This doubleword points to the entry point of the C driver code... + EXTRN _c_driver:WORD + +_DATA ENDS + + +; The _BSS segment contains uninitialized static data... +_BSS SEGMENT WORD PUBLIC 'BSS' + PUBLIC _STACK + +; Local variables for this module... +RHPTR DW 2 DUP (?) ; offset and segment of the request header +OLDSTK DW 2 DUP (?) ; original stack offset and segment + +; This is the stack while the C code is running... + DB STACKSIZE DUP (?) +_STACK LABEL WORD ; the address of a stack is at its _top_ ! + +_BSS ENDS + + +; WARNING! The _TEXT segment must be paragraph aligned! +_TEXT SEGMENT PARA PUBLIC 'CODE' + ASSUME CS:DGROUP, DS:DGROUP, SS:DGROUP, ES:NOTHING + + +; These words give the offsets of the _TEXT segment and the stack, both +; relative to the DGROUP. Note that you can't define use "DGROUP:_TEXT" +; as this generates a segment relocation record in the .EXE file which +; will prevent you from converting to a .COM file. The way its written +; works, but assumes that it is the first thing in this module. +CSOFF DW DGROUP:CSOFF +NEWSTK DW DGROUP:_STACK + + +; This is the entry for the STRATEGY procedure. DOS calls this routine +; with the address of the request header, but all the work is expected +; to occur in the INTERRUPT procedure. All we do here is to save the +; address of the request for later processing. Since this function is +; trivial, we never call any C code... + PUBLIC STRATEGY +STRATEGY PROC FAR + MOV CS:RHPTR,BX ; save the request header offset + MOV CS:RHPTR+2,ES ; and its segment + RET ; that's all there is to do +STRATEGY ENDP + + +; And now the INTERRUPT routine. This routine has to save all the +; registers, switch to the new stack, set up the segment registers, +; and call the C language driver routine while passing it the address +; of the request header (saved by the strategy routine). + PUBLIC INTERRUPT +INTERRUPT PROC FAR + PUSH DS ES AX BX CX DX DI SI BP + + CLI ; interrupts OFF while the stack is unsafe! + MOV CS:OLDSTK+2,SS ; save the current stack pointer + MOV CS:OLDSTK,SP ; ... + MOV BX,CS ; then setup the new stack + MOV SS,BX ; ... + MOV SP,NEWSTK ; ... + STI ; interrupts are safe once again + MOV AX,CSOFF ; compute the correct code segment address + SHR AX,4 ; ... for the _TEXT segment + ADD AX,BX ; ... + MOV _c_driver+2,AX ; fix the pointer appropriately + MOV DS,BX ; setup DS for the C code + CLD ; the C code will assume this state + + PUSH CS:RHPTR+2 ; pass the request header + PUSH CS:RHPTR ; address as a parameter + CALL DWORD PTR _c_driver; call the C entry point + + CLI ; interrupts OFF once again + MOV SS,CS:OLDSTK+2 ; and restore the original stack + MOV SP,CS:OLDSTK ; ... + STI ; ... + + POP BP SI DI DX CX BX AX ES DS + RET +INTERRUPT ENDP + + +_TEXT ENDS + + END diff --git a/XTMax/Drivers/SDPP/INTEGER.H b/XTMax/Drivers/SDPP/INTEGER.H new file mode 100644 index 0000000..4a7dcf5 --- /dev/null +++ b/XTMax/Drivers/SDPP/INTEGER.H @@ -0,0 +1,40 @@ +/*-------------------------------------------*/ +/* Integer type definitions for FatFs module */ +/*-------------------------------------------*/ + +#ifndef _INTEGER +#define _INTEGER + +#ifdef _WIN32 /* FatFs development platform */ + +#include +#include + +#else /* Embedded platform */ + +/* These types must be 16-bit, 32-bit or larger integer */ +typedef int INT; +typedef unsigned int UINT; + +/* These types must be 8-bit integer */ +typedef char CHAR; +typedef unsigned char UCHAR; +typedef unsigned char BYTE; + +/* These types must be 16-bit integer */ +typedef short SHORT; +typedef unsigned short USHORT; +typedef unsigned short WORD; +typedef unsigned short WCHAR; + +/* These types must be 32-bit integer */ +#ifndef DEFINEDLONG +#define DEFINEDLONG +typedef long LONG; +#endif +typedef unsigned long ULONG; +typedef unsigned long DWORD; + +#endif + +#endif diff --git a/XTMax/Drivers/SDPP/LICENSE.TXT b/XTMax/Drivers/SDPP/LICENSE.TXT new file mode 100644 index 0000000..5b6e7c6 --- /dev/null +++ b/XTMax/Drivers/SDPP/LICENSE.TXT @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/XTMax/Drivers/SDPP/MAKEFILE b/XTMax/Drivers/SDPP/MAKEFILE new file mode 100644 index 0000000..af3ce4b --- /dev/null +++ b/XTMax/Drivers/SDPP/MAKEFILE @@ -0,0 +1,26 @@ +# Makefile for the TU58 Device Driver project - RLA [12-Aug-94] + +CC=bcc -c -ms -Z -O -Ol -Oe +ASM=tasm -mx + +.c.obj: + $(CC) $< + +.asm.obj: + $(ASM) $* + +sd.sys: header.obj cprint.obj sd.obj sdmm.obj driver.obj + tlink -t -m -s -n header cprint sd sdmm driver, sd.sys + +sd.com: header.obj cprint.obj sd.obj sdmm.obj driver.obj + tlink -t -m -s -n header cprint sd sdmm driver, sd.sys + rename sd.sys sd.com + +clean: + del *.obj + del sd.sys + +driver.obj: cprint.c sdmm.c driver.c cprint.c cprint.h standard.h driver.h sd.h +sd.obj: sd.c sd.h standard.h driver.h +sdmm.obj: sdmm.c diskio.h integer.h +header.obj: header.asm diff --git a/XTMax/Drivers/SDPP/README.TXT b/XTMax/Drivers/SDPP/README.TXT new file mode 100644 index 0000000..c0dd791 --- /dev/null +++ b/XTMax/Drivers/SDPP/README.TXT @@ -0,0 +1,72 @@ + +SD card driver for parallel port + +I wrote this to simplify data transfer between my IBM PC and my laptop, because my laptop does +not have a 360k floppy drive but does have an SD card slot. + +WARNING: I take **no responsibility** for any damage to your computer, parallel port, or SD +card, or any data. You use this driver at your own risk. It is highly recommended you use +an expendable parallel port card with your expendable SD card, and your expendable data. +It is recommended that you use a level converter IC with between your 5 volt parallel port +outputs and the SD card 3.3 volt inputs. This project is intended as a fun hack for hobbyists +and enthusiasts and not for serious work. + +This driver is made available under the GNU General Public License version 2. It incorporates +modified code from ELM Chan Fat FS (http://elm-chan.org/fsw/ff/00index_e.html). + +Usage: + +In your config.sys file + +DEVICE=SD.SYS /d /k /p= /b= + +Loads and installs the SD card driver. + +/d = debugging mode (displays copious debugging messsages) +/k = use card detect signal to inform dos that card is attached +/p = partition number (1-4) to partition in MBR to use. Default: first available. +/b = port base index of parallel port, one of + 1=0x3BC, 2=0x378, 3=0x278, 4=0x3E8, 5=0x2E8 + Default: 0x378 + +For best results, format your SD card with a FAT16 partition which is less than 32 MB in size. +NOTE: Many versions of DOS don't know how to handle FAT32, and many can't have FAT16 with a +partition size greater than 32 MB. Therefore, if you want to play with this, make your parition on +the card FAT16 and less than 32 MB. This assures the best compatibility. You can have multiple copies of the +driver loaded if there are multiple partitions on your SD card you want to use simultaneously. + +I have used Adafruit's microSD adapter + (http://www.adafruit.com/products/254?gclid=CLH7l4iEkrwCFQPNOgod7BkAQA) +if you want a relatively simple way to interface your PC parallel port to +the SD card. The adapter provides the 3.3 volts needed to power the SD card, as well +as a the level shifting between the 5 volt parallel port output and the 3.3 volt input. +If you directly connect a 5 volt output to a 3.3 volt input, you risk latching up the +3.3 volt input and damaging the card or computer from exceesive current. +Some have used series resistors instead of the level converters, but I found this +to not be that reliable and still may have this problem. Also, some SD cards MISO/DO +outputs are unable to drive a TTL input of some parallel ports, so you may need to add +a buffer between the two as well. I have found quite a bit of variability in the drive +current required for the inputs of various parallel ports. + +The driver uses the very slow serial peripheral interface (SPI) mode of the SD card. The +speed, which depends on your PC speed, could be as slow as 10 kilobytes/second. This is +not a replacement for your hard drive. Your parallel port should be configured for standard +mode (not bidirectional) if applicable. + +The connections between the parallel port and the SD card are as follows: + +Parallel port SD card + +PIN 25 signal GND GND (Vss) ++3.3V Vdd (power) +PIN 2 signal D0 CMD / MOSI / DI (SPI data in) +PIN 3 signal D1 SCLK / CLK (SPI clock) +PIN 4 signal D2 DAT3 / CS (SPI chip select) +PIN 13 signal SELECT DAT0 / MISO / DO (SPI data out) +PIN 11 signal BUSY Card detect (if you SD card slot has one) + +For similar setups, look up parallel port to JTAG adapters which are used for in circuit +programming and debugging. + +Good luck and be careful! + diff --git a/XTMax/Drivers/SDPP/SD.C b/XTMax/Drivers/SDPP/SD.C new file mode 100644 index 0000000..cde528d --- /dev/null +++ b/XTMax/Drivers/SDPP/SD.C @@ -0,0 +1,236 @@ +/* sd.c */ +/* */ +/* Copyright (C) 1994 by Robert Armstrong */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT- */ +/* ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */ +/* Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, visit the website of the Free */ +/* Software Foundation, Inc., www.gnu.org. */ +/* */ +/* */ +/* The functions provided are: */ +/* */ +/* SDInitialize - establish two way communications with the drive */ +/* SDRead - read one 512 byte logical block from the tape */ +/* SDWrite - write one 512 byte logical block to the tape */ +/* SDMediaCheck - see if card detect has changed */ +/* */ +/* Normally the SDInitialize routine would be called */ +/* during the DOS device driver initialization, and then the SDRead and */ +/* */ + +#include /* needed for NULL, etc */ +#include /* memset, memcopy, etc */ +#include "standard.h" /* all definitions for this project */ +#include "sd.h" /* device protocol and data defintions */ +#include "diskio.h" /* stuff from sdmm.c module */ +#include "driver.h" +#include "cprint.h" + +DWORD partition_offset = 0; + +/* FatFs refers the members in the FAT structures as byte array instead of +/ structure member because the structure is not binary compatible between +/ different platforms */ + +#define BS_jmpBoot 0 /* Jump instruction (3) */ +#define BS_OEMName 3 /* OEM name (8) */ +#define BPB_BytsPerSec 11 /* Sector size [byte] (2) */ +#define BPB_SecPerClus 13 /* Cluster size [sector] (1) */ +#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (2) */ +#define BPB_NumFATs 16 /* Number of FAT copies (1) */ +#define BPB_RootEntCnt 17 /* Number of root directory entries for FAT12/16 (2) */ +#define BPB_TotSec16 19 /* Volume size [sector] (2) */ +#define BPB_Media 21 /* Media descriptor (1) */ +#define BPB_FATSz16 22 /* FAT size [sector] (2) */ +#define BPB_SecPerTrk 24 /* Track size [sector] (2) */ +#define BPB_NumHeads 26 /* Number of heads (2) */ +#define BPB_HiddSec 28 /* Number of special hidden sectors (4) */ +#define BPB_TotSec32 32 /* Volume size [sector] (4) */ +#define BS_DrvNum 36 /* Physical drive number (2) */ +#define BS_BootSig 38 /* Extended boot signature (1) */ +#define BS_VolID 39 /* Volume serial number (4) */ +#define BS_VolLab 43 /* Volume label (8) */ +#define BS_FilSysType 54 /* File system type (1) */ +#define BPB_FATSz32 36 /* FAT size [sector] (4) */ +#define BPB_ExtFlags 40 /* Extended flags (2) */ +#define BPB_FSVer 42 /* File system version (2) */ +#define BPB_RootClus 44 /* Root directory first cluster (4) */ +#define BPB_FSInfo 48 /* Offset of FSINFO sector (2) */ +#define BPB_BkBootSec 50 /* Offset of backup boot sector (2) */ +#define BS_DrvNum32 64 /* Physical drive number (2) */ +#define BS_BootSig32 66 /* Extended boot signature (1) */ +#define BS_VolID32 67 /* Volume serial number (4) */ +#define BS_VolLab32 71 /* Volume label (8) */ +#define BS_FilSysType32 82 /* File system type (1) */ +#define FSI_LeadSig 0 /* FSI: Leading signature (4) */ +#define FSI_StrucSig 484 /* FSI: Structure signature (4) */ +#define FSI_Free_Count 488 /* FSI: Number of free clusters (4) */ +#define FSI_Nxt_Free 492 /* FSI: Last allocated cluster (4) */ +#define MBR_Table 446 /* MBR: Partition table offset (2) */ +#define SZ_PTE 16 /* MBR: Size of a partition table entry */ +#define BS_55AA 510 /* Boot sector signature (2) */ + + +BYTE local_buffer[BLOCKSIZE]; + +#define LD_WORD(x) *((WORD *)(BYTE *)(x)) +#define LD_DWORD(x) *((DWORD *)(BYTE *)(x)) + +/*-----------------------------------------------------------------------*/ +/* Load a sector and check if it is an FAT boot sector */ +/*-----------------------------------------------------------------------*/ + +static +BYTE check_fs (BYTE unit, + /* 0:FAT boor sector, 1:Valid boor sector but not FAT, */ + /* 2:Not a boot sector, 3:Disk error */ + DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ +) +{ + if (disk_read (unit, local_buffer, sect, 1) != RES_OK) + return 3; + if (LD_WORD(&local_buffer[BS_55AA]) != 0xAA55) /* Check boot record signature (always placed at offset 510 even if the sector size is >512) */ + return 2; + if ((LD_DWORD(&local_buffer[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ + return 0; + if ((LD_DWORD(&local_buffer[BS_FilSysType32]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ + return 0; + return 1; +} + + +/*-----------------------------------------------------------------------*/ +/* Find logical drive and check if the volume is mounted */ +/*-----------------------------------------------------------------------*/ + +static +int find_volume ( + BYTE unit, + BYTE partno, + bpb_t *bpb +) +{ + BYTE fmt; + DSTATUS stat; + WORD secsize; + DWORD bsect; + + stat = disk_status(unit); + if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ + return 0; /* The file system object is valid */ + } + + /* The file system object is not valid. */ + /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */ + + stat = disk_initialize(unit); /* Initialize the physical drive */ + if (stat & STA_NOINIT) /* Check if the initialization succeeded */ + return -1; /* Failed to initialize due to no medium or hard error */ + + /* Find an FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */ + bsect = 0; + fmt = check_fs(unit, bsect); /* Load sector 0 and check if it is an FAT boot sector as SFD */ + if (fmt == 1 || (!fmt && (partno))) { /* Not an FAT boot sector or forced partition number */ + UINT i; + DWORD br[4]; + + for (i = 0; i < 4; i++) { /* Get partition offset */ + BYTE *pt = &local_buffer[MBR_Table + i * SZ_PTE]; + br[i] = pt[4] ? LD_DWORD(&pt[8]) : 0; + } + i = partno; /* Partition number: 0:auto, 1-4:forced */ + if (i) i--; + do { /* Find an FAT volume */ + bsect = br[i]; + fmt = bsect ? check_fs(unit, bsect) : 2; /* Check the partition */ + } while (!partno && fmt && ++i < 4); + } + if (fmt == 3) return -2; /* An error occured in the disk I/O layer */ + if (fmt) return -3; /* No FAT volume is found */ + + /* An FAT volume is found. Following code initializes the file system object */ + + secsize = LD_WORD(local_buffer + BPB_BytsPerSec); + if (secsize != BLOCKSIZE) + return -3; + + bpb->sector_size = BLOCKSIZE; + bpb->allocation_unit = local_buffer[BPB_SecPerClus]; /* Number of sectors per cluster */ + bpb->reserved_sectors = LD_WORD(local_buffer+BPB_RsvdSecCnt); /* Number of reserved sectors */ + if (!bpb->reserved_sectors) return -3; /* (Must not be 0) */ + bpb->fat_count = local_buffer[BPB_NumFATs]; /* Number of FAT copies */ + if (bpb->fat_count == 0) + bpb->fat_count = 2; + bpb->directory_size = LD_WORD(local_buffer+BPB_RootEntCnt); + bpb->total_sectors = LD_WORD(local_buffer+BPB_TotSec16); + if (!bpb->total_sectors) + bpb->sector_count = LD_DWORD(local_buffer+BPB_TotSec32); + else + bpb->sector_count = bpb->total_sectors; + bpb->media_descriptor = local_buffer[BPB_Media]; + bpb->fat_sectors = LD_WORD(local_buffer+BPB_FATSz16); /* Number of sectors per FAT */ + bpb->track_size = LD_WORD(local_buffer+BPB_SecPerTrk); /* Number of sectors per cluster */ + bpb->head_count = LD_WORD(local_buffer+BPB_NumHeads); /* Number of sectors per cluster */ + bpb->hidden_sectors = 1; + + partition_offset = bsect; + return 0; +} + + +/* SDInitialize */ +PUBLIC BOOLEAN SDInitialize (BYTE unit, BYTE partno, bpb_t *bpb) +{ + if (find_volume(unit,partno,bpb) < 0) + return FALSE; + return TRUE; +} + +/* SDMediaCheck */ +PUBLIC BOOLEAN SDMediaCheck (BYTE unit) +{ + return (disk_result(unit) == RES_OK) ? FALSE : TRUE; +} + +/* SDRead */ +/* IMPORTANT! Blocks are always 512 bytes! Never more, never less. */ +/* */ +/* INPUTS: */ +/* unit - selects tape drive 0 (left) or 1 (right) */ +/* lbn - logical block number to be read [0..511] */ +/* buffer - address of 512 bytes to receive the data read */ +/* */ +/* RETURNS: operation status as reported by the TU58 */ +/* */ +PUBLIC int SDRead (WORD unit, DWORD lbn, BYTE far *buffer, WORD count) +{ + return disk_read (unit, buffer, lbn + partition_offset, count); +} + + +/* SDWrite */ +/* IMPORTANT! Blocks are always 512 bytes! Never more, never less. */ +/* */ +/* INPUTS: */ +/* unit - selects tape drive 0 (left) or 1 (right) */ +/* lbn - logical block number to be read [0..511] */ +/* buffer - address of 512 bytes containing the data to write */ +/* verify - TRUE to ask the TU58 for a verification pass */ +/* */ +/* RETURNS: operation status as reported by the TU58 */ +/* */ +PUBLIC int SDWrite (WORD unit, DWORD lbn, BYTE far *buffer, WORD count) +{ + return disk_write (unit, buffer, lbn + partition_offset, count); +} + diff --git a/XTMax/Drivers/SDPP/SD.H b/XTMax/Drivers/SDPP/SD.H new file mode 100644 index 0000000..3149e98 --- /dev/null +++ b/XTMax/Drivers/SDPP/SD.H @@ -0,0 +1,22 @@ +/* sd.h - SD card driver glue */ + +#ifndef _SD_H +#define _SD_H + +#include "integer.h" +#include "driver.h" + +#define BLOCKSIZE 512 + +extern DWORD partition_offset; + +/* SDInitialize - establish two way communications with the drive */ +BOOLEAN SDInitialize (BYTE unit, BYTE partno, bpb_t *bpb); +/* SDRead - read one 512 byte logical block from the tape */ +int SDRead (WORD, DWORD, BYTE far *, WORD count); +/* SDWrite - write one 512 byte logical block to the tape */ +int SDWrite (WORD, DWORD, BYTE far *, WORD count); +/* SDMediaCheck - check if media changed */ +BOOLEAN SDMediaCheck (BYTE unit); + +#endif diff --git a/XTMax/Drivers/SDPP/SD.SYS b/XTMax/Drivers/SDPP/SD.SYS new file mode 100644 index 0000000..ebeab06 Binary files /dev/null and b/XTMax/Drivers/SDPP/SD.SYS differ diff --git a/XTMax/Drivers/SDPP/SDMM.C b/XTMax/Drivers/SDPP/SDMM.C new file mode 100644 index 0000000..9e39e15 --- /dev/null +++ b/XTMax/Drivers/SDPP/SDMM.C @@ -0,0 +1,655 @@ +/*------------------------------------------------------------------------/ +/ Foolproof MMCv3/SDv1/SDv2 (in SPI mode) control module +/-------------------------------------------------------------------------/ +/ +/ Copyright (C) 2013, ChaN, all right reserved. +/ +/ * This software is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/-------------------------------------------------------------------------/ + Features and Limitations: + + * No Media Change Detection + Application program needs to perform f_mount() after media change. + +/-------------------------------------------------------------------------*/ + +#include + +#include "diskio.h" /* Common include file for FatFs and disk I/O layer */ +#include "cprint.h" + +/*-------------------------------------------------------------------------*/ +/* Platform dependent macros and functions needed to be modified */ +/*-------------------------------------------------------------------------*/ + +static WORD portbases[5] = {0x3BC,0x378,0x278,0x3E8,0x2E8}; + +BYTE sd_card_check = 0; +BYTE portbase = 2; + +WORD DATAPORT=0x378; +WORD CONTROLPORT=0x379; + +#define VAR_INIT() {CONTROLPORT=DATAPORT+1;} + +#if 1 +#define TOUTCHR(x) +#define TOUTHEX(x) +#define TOUTWORD(x) +#else +#define TOUTCHR(x) toutchr(x) +#define TOUTHEX(x) touthex(x) +#define TOUTWORD(x) toutword(x) + +static BYTE toutchr (unsigned char ch) +{ + _DI = _SI = 0; + _AL = ch; _AH = 0xE; _BX = 0; + asm INT 0x10; + return 0; +} + +static BYTE touthex(unsigned char c) +{ + char d = c >> 4; + toutchr(d > 9 ? d+('A'-10) : d+'0'); + d = c & 0x0F; + toutchr(d > 9 ? d+('A'-10) : d+'0'); + return 0; +} + +static BYTE toutword(WORD x) +{ + touthex(x >> 8); + touthex(x); + return 0; +} + +#endif + +void setportbase(BYTE val) +{ + if ((val >= 1) && (val <= (sizeof(portbases)/sizeof(portbases[0])) )) + DATAPORT = portbases[val-1]; + VAR_INIT(); +} + +static +void dly_us (UINT n) +{ + _CX = n; + loopit: + _asm { + loop loopit + } +} + +#define NOSHIFT + +#ifdef NOSHIFT + +DWORD dwordlshift(DWORD d, int n) +{ + int i; + WORD a = ((WORD *)d)[0]; + WORD b = ((WORD *)d)[1]; + DWORD r; + + for (i=0;i>= 1; + a |= (b & 0x1) ? 0x8000 : 0; + b >>= 1; + } + ((WORD *)r)[0] = a; + ((WORD *)r)[1] = b; + return r; +} + +#define DWORDRSHIFT(d,n) dwordrshift(d,n) + +#else + +#define DWORDLSHIFT(d,n) ((d) << (n)) +#define DWORDRSHIFT(d,n) ((d) >> (n)) + +#endif + +/*-------------------------------------------------------------------------- + + Module Private Functions + +---------------------------------------------------------------------------*/ + +/* MMC/SD command (SPI mode) */ +#define CMD0 (0) /* GO_IDLE_STATE */ +#define CMD1 (1) /* SEND_OP_COND */ +#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */ +#define CMD8 (8) /* SEND_IF_COND */ +#define CMD9 (9) /* SEND_CSD */ +#define CMD10 (10) /* SEND_CID */ +#define CMD12 (12) /* STOP_TRANSMISSION */ +#define CMD13 (13) /* SEND_STATUS */ +#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */ +#define CMD16 (16) /* SET_BLOCKLEN */ +#define CMD17 (17) /* READ_SINGLE_BLOCK */ +#define CMD18 (18) /* READ_MULTIPLE_BLOCK */ +#define CMD23 (23) /* SET_BLOCK_COUNT */ +#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */ +#define CMD24 (24) /* WRITE_BLOCK */ +#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */ +#define CMD32 (32) /* ERASE_ER_BLK_START */ +#define CMD33 (33) /* ERASE_ER_BLK_END */ +#define CMD38 (38) /* ERASE */ +#define CMD55 (55) /* APP_CMD */ +#define CMD58 (58) /* READ_OCR */ + + +static +DSTATUS Stat = STA_NOINIT; /* Disk status */ + +static +BYTE CardType; /* b0:MMC, b1:SDv1, b2:SDv2, b3:Block addressing */ + + + +/*-----------------------------------------------------------------------*/ +/* Transmit bytes to the card (bitbanging) */ +/*-----------------------------------------------------------------------*/ + +static +void xmit_mmc ( + const BYTE DOSFAR * buff, /* Data to be sent */ + UINT bc /* Number of bytes to send */ +) +{ +#if 1 + BYTE d; + do { + d = *buff++; /* Get a byte to be sent */ + outp(DATAPORT, d); + } while (--bc); +#else + // Requires to add `-2' in the CC command line in the Makefile. + _asm { + mov cx,bc + mov dx,DATAPORT + push ds + lds si,dword ptr buff + rep outsb + pop ds + } +#endif +} + + + +/*-----------------------------------------------------------------------*/ +/* Receive bytes from the card (bitbanging) */ +/*-----------------------------------------------------------------------*/ + +static +void rcvr_mmc ( + BYTE DOSFAR *buff, /* Pointer to read buffer */ + UINT bc /* Number of bytes to receive */ +) +{ +#if 1 + BYTE r; + + do { + r = inp(DATAPORT); + *buff++ = r; /* Store a received byte */ + } while (--bc); +#else + // Requires to add `-2' in the CC command line in the Makefile. + _asm { + mov cx,bc + mov dx,DATAPORT + push es + les di,dword ptr buff + rep insb + pop es + } +#endif +} + +/*-----------------------------------------------------------------------*/ +/* Wait for card ready */ +/*-----------------------------------------------------------------------*/ + +static +int wait_ready (void) /* 1:OK, 0:Timeout */ +{ + BYTE d; + UINT tmr; + + + for (tmr = 5000; tmr; tmr--) { /* Wait for ready in timeout of 500ms */ + d = inp(DATAPORT); + if (d == 0xFF) break; + dly_us(100); + } + + return tmr ? 1 : 0; +} + + + +/*-----------------------------------------------------------------------*/ +/* Deselect the card and release SPI bus */ +/*-----------------------------------------------------------------------*/ + +static +void deselect (void) +{ + outp(CONTROLPORT, 1); // CS high +#if 0 + outp(DATAPORT, 0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */ +#endif +} + + + +/*-----------------------------------------------------------------------*/ +/* Select the card and wait for ready */ +/*-----------------------------------------------------------------------*/ + +static +int select (void) /* 1:OK, 0:Timeout */ +{ + BYTE d; + + outp(CONTROLPORT, 0); // CS low +#if 0 + (void)inp(DATAPORT); /* Dummy clock (force DO enabled) */ +#endif + + if (wait_ready()) return 1; /* OK */ + deselect(); + return 0; /* Failed */ +} + + + +/*-----------------------------------------------------------------------*/ +/* Receive a data packet from the card */ +/*-----------------------------------------------------------------------*/ + +static +int rcvr_datablock ( /* 1:OK, 0:Failed */ + BYTE DOSFAR *buff, /* Data buffer to store received data */ + UINT btr /* Byte count */ +) +{ + BYTE d; + UINT tmr; + + + for (tmr = 1000; tmr; tmr--) { /* Wait for data packet in timeout of 100ms */ + d = inp(DATAPORT); + if (d != 0xFF) break; + dly_us(100); + } + if (d != 0xFE) { + return 0; /* If not valid data token, return with error */ + } + + rcvr_mmc(buff, btr); /* Receive the data block into buffer */ + (void)inp(DATAPORT); (void)inp(DATAPORT); /* Discard CRC */ + + return 1; /* Return with success */ +} + + + +/*-----------------------------------------------------------------------*/ +/* Send a data packet to the card */ +/*-----------------------------------------------------------------------*/ + +static +int xmit_datablock ( /* 1:OK, 0:Failed */ + const BYTE DOSFAR *buff, /* 512 byte data block to be transmitted */ + BYTE token /* Data/Stop token */ +) +{ + BYTE d; + + + if (!wait_ready()) return 0; + + d = token; + xmit_mmc(&d, 1); /* Xmit a token */ + if (token != 0xFD) { /* Is it data token? */ + xmit_mmc(buff, 512); /* Xmit the 512 byte data block to MMC */ + (void)inp(DATAPORT); (void)inp(DATAPORT); /* Xmit dummy CRC (0xFF,0xFF) */ + d = inp(DATAPORT);; /* Receive data response */ + if ((d & 0x1F) != 0x05) /* If not accepted, return with error */ + { + return 0; + } + } + + return 1; +} + + + +/*-----------------------------------------------------------------------*/ +/* Send a command packet to the card */ +/*-----------------------------------------------------------------------*/ + +static +BYTE send_cmd ( /* Returns command response (bit7==1:Send failed)*/ + BYTE cmd, /* Command byte */ + DWORD arg /* Argument */ +) +{ + BYTE n, d, buf[6]; + + + if (cmd & 0x80) { /* ACMD is the command sequense of CMD55-CMD */ + cmd &= 0x7F; + n = send_cmd(CMD55, 0); + if (n > 1) return n; + } + + /* Select the card and wait for ready except to stop multiple block read */ + if (cmd != CMD12) { + deselect(); + if (!select()) return 0xFF; + } + + /* Send a command packet */ + buf[0] = 0x40 | cmd; /* Start + Command index */ + #ifdef NOSHIFT + buf[1] = ((BYTE *)&arg)[3]; /* Argument[31..24] */ + buf[2] = ((BYTE *)&arg)[2]; /* Argument[23..16] */ + buf[3] = ((BYTE *)&arg)[1]; /* Argument[15..8] */ + buf[4] = ((BYTE *)&arg)[0]; /* Argument[7..0] */ + #else + buf[1] = (BYTE)(arg >> 24); /* Argument[31..24] */ + buf[2] = (BYTE)(arg >> 16); /* Argument[23..16] */ + buf[3] = (BYTE)(arg >> 8); /* Argument[15..8] */ + buf[4] = (BYTE)arg; /* Argument[7..0] */ + #endif + n = 0x01; /* Dummy CRC + Stop */ + if (cmd == CMD0) n = 0x95; /* (valid CRC for CMD0(0)) */ + if (cmd == CMD8) n = 0x87; /* (valid CRC for CMD8(0x1AA)) */ + buf[5] = n; + TOUTCHR('L'); + TOUTHEX(buf[0]); + TOUTHEX(buf[1]); + TOUTHEX(buf[2]); + TOUTHEX(buf[3]); + TOUTHEX(buf[4]); + TOUTHEX(buf[5]); + xmit_mmc(buf, 6); + + /* Receive command response */ + if (cmd == CMD12) (void)inp(DATAPORT); /* Skip a stuff byte when stop reading */ + n = 10; /* Wait for a valid response in timeout of 10 attempts */ + do + { + d = inp(DATAPORT); + } + while ((d & 0x80) && (--n)); + TOUTCHR('P'); + TOUTHEX(d); + return d; /* Return with the response value */ +} + + + +/*-------------------------------------------------------------------------- + + Public Functions + +---------------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* Get Disk Status */ +/*-----------------------------------------------------------------------*/ + +DSTATUS disk_status ( + BYTE drv /* Drive number (always 0) */ +) +{ + if (drv) return STA_NOINIT; + if ((sd_card_check) && (inp(CONTROLPORT) & 0x80)) + { + Stat = STA_NOINIT; + return STA_NOINIT; + } + return Stat; +} + +DRESULT disk_result ( + BYTE drv /* Drive number (always 0) */ +) +{ + if (drv) return RES_NOTRDY; + if ((sd_card_check) && (inp(CONTROLPORT) & 0x80)) + { + Stat = STA_NOINIT; + return RES_NOTRDY; + } + return RES_OK; +} + + +/*-----------------------------------------------------------------------*/ +/* Initialize Disk Drive */ +/*-----------------------------------------------------------------------*/ + +DSTATUS disk_initialize ( + BYTE drv /* Physical drive nmuber (0) */ +) +{ + BYTE n, ty, cmd, buf[4]; + UINT tmr; + DSTATUS s; + + setportbase(portbase); + + if (drv) return RES_NOTRDY; + if ((sd_card_check) && (inp(CONTROLPORT) & 0x80)) + return RES_NOTRDY; + + ty = 0; + for (n = 5; n; n--) { + outp(CONTROLPORT, 1); // CS high + dly_us(10000); /* 10ms. time for SD card to power up */ + for (tmr = 10; tmr; tmr--) outp(DATAPORT, 0xFF); /* Apply 80 dummy clocks and the card gets ready to receive command */ + if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */ + if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */ + rcvr_mmc(buf, 4); /* Get trailing return value of R7 resp */ + if (buf[2] == 0x01 && buf[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ + for (tmr = 1000; tmr; tmr--) { /* Wait for leaving idle state (ACMD41 with HCS bit) */ + if (send_cmd(ACMD41, 1UL << 30) == 0) break; + dly_us(1000); + } + if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ + rcvr_mmc(buf, 4); + ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 */ + } + } + } else { /* SDv1 or MMCv3 */ + if (send_cmd(ACMD41, 0) <= 1) { + ty = CT_SD1; cmd = ACMD41; /* SDv1 */ + } else { + ty = CT_MMC; cmd = CMD1; /* MMCv3 */ + } + for (tmr = 1000; tmr; tmr--) { /* Wait for leaving idle state */ + if (send_cmd(cmd, 0) == 0) break; + dly_us(1000); + } + if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */ + ty = 0; + } + break; + } + } + CardType = ty; + s = ty ? 0 : STA_NOINIT; + Stat = s; + + deselect(); + + return s; +} + + + +/*-----------------------------------------------------------------------*/ +/* Read Sector(s) */ +/*-----------------------------------------------------------------------*/ + +DRESULT disk_read ( + BYTE drv, /* Physical drive nmuber (0) */ + BYTE DOSFAR *buff, /* Pointer to the data buffer to store read data */ + DWORD sector, /* Start sector number (LBA) */ + UINT count /* Sector count (1..128) */ +) +{ + DRESULT dr = disk_result(drv); + if (dr != RES_OK) return dr; + + if (!(CardType & CT_BLOCK)) sector = DWORDLSHIFT(sector,9); /* Convert LBA to byte address if needed */ + + if (count == 1) { /* Single block read */ + if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */ + && rcvr_datablock(buff, 512)) + count = 0; + } + else { /* Multiple block read */ + if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */ + do { + if (!rcvr_datablock(buff, 512)) break; + buff += 512; + } while (--count); + send_cmd(CMD12, 0); /* STOP_TRANSMISSION */ + } + } + deselect(); + + return count ? RES_ERROR : RES_OK; +} + + + +/*-----------------------------------------------------------------------*/ +/* Write Sector(s) */ +/*-----------------------------------------------------------------------*/ + +DRESULT disk_write ( + BYTE drv, /* Physical drive nmuber (0) */ + const BYTE DOSFAR *buff, /* Pointer to the data to be written */ + DWORD sector, /* Start sector number (LBA) */ + UINT count /* Sector count (1..128) */ +) +{ + DRESULT dr = disk_result(drv); + if (dr != RES_OK) return dr; + + if (!(CardType & CT_BLOCK)) sector = DWORDLSHIFT(sector,9); /* Convert LBA to byte address if needed */ + + if (count == 1) { /* Single block write */ + if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */ + && xmit_datablock(buff, 0xFE)) + count = 0; + } + else { /* Multiple block write */ + if (CardType & CT_SDC) send_cmd(ACMD23, count); + if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */ + do { + if (!xmit_datablock(buff, 0xFC)) break; + buff += 512; + } while (--count); + if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */ + count = 1; + if (!wait_ready()) count = 1; /* Wait for card to write */ + } + } + deselect(); + + return count ? RES_ERROR : RES_OK; +} + + +/*-----------------------------------------------------------------------*/ +/* Miscellaneous Functions */ +/*-----------------------------------------------------------------------*/ + +DRESULT disk_ioctl ( + BYTE drv, /* Physical drive nmuber (0) */ + BYTE ctrl, /* Control code */ + void DOSFAR *buff /* Buffer to send/receive control data */ +) +{ + DRESULT res; + BYTE n, csd[16]; + DWORD cs; + DRESULT dr = disk_result(drv); + if (dr != RES_OK) return dr; + + res = RES_ERROR; + switch (ctrl) { + case CTRL_SYNC : /* Make sure that no pending write process */ + if (select()) res = RES_OK; + break; + + case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */ + if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { + if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */ + cs = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1; + *(DWORD DOSFAR *)buff = DWORDLSHIFT(cs,10); + } else { /* SDC ver 1.XX or MMC */ + n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2; + cs = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1; + *(DWORD DOSFAR *)buff = DWORDLSHIFT(cs,n-9); + } + res = RES_OK; + } + break; + + case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */ + *(DWORD DOSFAR *)buff = 128; + res = RES_OK; + break; + + default: + res = RES_PARERR; + } + + deselect(); + + return res; +} + + diff --git a/XTMax/Drivers/SDPP/STANDARD.H b/XTMax/Drivers/SDPP/STANDARD.H new file mode 100644 index 0000000..cc9dd17 --- /dev/null +++ b/XTMax/Drivers/SDPP/STANDARD.H @@ -0,0 +1,106 @@ +/* standard.h - standard, project wide, declarations */ +/* */ +/* Copyright (C) 1994 by Robert Armstrong */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT- */ +/* ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */ +/* Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, visit the website of the Free */ +/* Software Foundation, Inc., www.gnu.org. */ + + +/* Datatypes of a known size ... */ +typedef unsigned char BYTE; /* 8 bits, unsigned */ +typedef unsigned short WORD; /* 16 " " */ +#ifndef DEFINEDLONG +#define DEFINEDLONG +typedef unsigned long LONG; /* 32 " " */ +#endif + + +/* The BOOLEAN type and associated constants ... */ +typedef unsigned char BOOLEAN;/* any TRUE/FALSE result */ +#define FALSE (0) /* logical falsity */ +#define TRUE (~FALSE)/* if it's not FALSE, it's ... */ + + +/* This magic declaration modifier will make the symbol defined be */ +/* invisible to the linker. For example, "PRIVATE int foo;" or even */ +/* "PRIVATE void fred () { ...}". This is used extensively to restrict */ +/* the scope of a global declaration to the current module. */ +#define PRIVATE static /* this works for most compilers! */ + + +/* And this magic declaration modifier guarantees that the symbol so */ +/* defined will be visible to other modules. It is the opposite of */ +/* "PRIVATE". In C this is the default condition anyway, so this macro */ +/* mostly serves as documentation. */ +#define PUBLIC /* this is the way things are anyway */ + + +/* Extract the high and low bytes of a 16 bit value... */ +#define HIGH(x) (((x) >> 8) & 0xFF) +#define LOW(x) ((x) & 0xFF) + +/* Test a value for odd/even... */ +#define ODD(x) (((x) & 1) != 0) + + +/* These macros provide access to specific 8088 family hardware ins- */ +/* tructions. From a performance viewpoint, it is highly desirable that */ +/* these macros not be implemented by subroutine calls, but rather that */ +/* they expand directly to inline assembler instructions. */ + +#ifdef __TURBOC__ +/* These macros turn the interrupt system on and off. They should */ +/* generate the STI (0xFB) and CLI (0xFA) instructions... */ +#define INT_ON asm sti +#define INT_OFF asm cli + +/* These macros read and write a bytes from an I/O port. They should */ +/* generate the 0xE5 (IN AL,DX) or 0xEE (OUT DX,AL) instructions... */ +#define INBYTE(p,v) { _DX = (p); asm IN AL,DX; v = _AL; } +#define OUTBYTE(p,v) { _DX = (p); _AL = (v); asm OUT DX,AL; } + +/* These macros will set or clear specific bit(s) in an I/O port. */ +/* They work by first reading the port, seting or clearing the bit(s), */ +/* and then writing the port. Needless to say, they can only be used */ +/* on ports that can safely be both read and written! */ +#define IOSETBIT(p,m) { _DX = (p); _BL = (m); \ + asm IN AL,DX; asm OR AL,BL; asm OUT DX,AL; } +#define IOCLRBIT(p,m) { _DX = (p); _BL = ~(m); \ + asm IN AL,DX; asm AND AL,BL; asm OUT DX,AL; } + +/* These macros use the DOS INT 21H functions to get and set the */ +/* contents of interrupt vectors. They are used to save and restore */ +/* the serial port interrupt service routine... */ +#define GETVECTOR(v,a) { _AL = (v); _AH = 0x35; asm INT 0x21; \ + asm MOV WORD PTR a, BX; asm MOV WORD PTR a+2, ES; } +#define SETVECTOR(v,a) { _AL = (v); _AH = 0x25; asm PUSH DS; \ + asm LDS DX, DWORD PTR a; \ + asm INT 0x21; asm POP DS; } +#define JMPVECTOR(a) { asm JMP DWORD PTR a; } + + +/* Compute dst += src with end-around carry, just like the TU58 does... */ +#define ADC(dst,src) { asm MOV AX, dst; asm ADD AX, src; \ + asm ADC AX, 0; asm MOV dst, AX; } + +#endif /* ifdef __TURBOC__ */ + + +/* Debugging output routines... */ +void outchr (char); +void outstr (char *); +void outdec (int); +void outhex (unsigned, int); +void outcrlf (void); +void cprintf (char near *, ...);