;
;       ReSizeable RAMDisk device driver
;
;       Copyright (C) 1992-1996, 2005 Marko Kohtala
;       Released under GNU GPL, read the file 'COPYING' for more information

[list -]
;=== Push trace listing source: dosstruc.mac
%include "dosstruc.mac" ; NASM included file
;=== Pop trace listing source
%include "define.mac"
%include "lmacros3.mac"
[list +]

%define DR_ATTRIBUTES DHATTR_NOFAT | DHATTR_OPENCLOSE


;**************************************************************************
;
;                Device driver start and the structures
;
;**************************************************************************

section D_SEG

;                org     0
; The following is to be considered as both a device driver header and
; as a starting point for the configuration table. This driver will be
; identified by its segment address and this structure must be at offset
; 0.

                ; Device driver header
drhdr_next      dd      -1              ; Pointer to next device (now last)
drhdr_attr      dw      DR_ATTRIBUTES
drhdr_strategy  dw      j_strategy	; Offset to strategy function
drhdr_commands  dw      commands	; Offset to commands function
drhdr_units     db      1               ; Number of units

dr_volume       label byte
dr_ID           db 'SRD'                ; SRDISK signature (3 char)
dr_memory       db "MULT"		; Memory type identifier (4 char)
dr_version      db SRD_VERSION          ; Device driver version (4 char)
                db 0                    ; null to end volume label
dr_v_format     db -1			; Configuration format version
dr_conf         dw -1			; Pointer to drive configuration

j_strategy:	fill 3, 90h, jmp strategy
commands:
	les bx, [cs:req_ptr]
	mov word [es:bx + rhStatus], ERROR | DONE | UNKNOWN_COMMAND
	retf

%define MSGLIST
%define BINLIST

%macro payload 2.nolist
 %xdefine MSGLIST MSGLIST, %%message:, {asciz %1}
 %xdefine BINLIST BINLIST, %%payload:, {incbin %2}, {align 16, db 38}, %%payload_end:
	dw %%message
	dw %%payload
	dw words(%%payload_end - %%payload)
%endmacro

	struc TABLEENTRY
teName:		resw 1
tePayload:	resw 1
teAmountWords:	resw 1
	endstruc

%macro multiline 1-*.nolist
 %rep %0
	%1
  %rotate 1
 %endrep
%endmacro

	align 2, db 0
table:
		; first entry is also default
	payload "XMS", "srdxms.sys"
	payload "XMSS", "srdxmss.sys"
	payload "EMS", "srdems.sys"
	payload "EMS3", "srdems3.sys"
	payload "EMSS", "srdemss.sys"
	payload "DUMMY", "srdummy.sys"
.end:

req_ptr         dd 0                    ; Request structure pointer

multiline MSGLIST

	align 16, db 0
multiline BINLIST

strategy:
                mov word ptr [cs:req_ptr],bx
                mov word ptr [cs:req_ptr+2],es

                pushf
                push ax
                push bx
                push cx
                push dx
                push si
                push di
                push ds
                push es

                cld
		lds si, [cs:req_ptr]
                cmp byte [si + rhFunction], 0
                je .init
			; NC
                mov word [si + rhStatus], ERROR | DONE | UNKNOWN_COMMAND
.chain:
		stc
.ret_NC:
                pop es
                pop ds
                pop di
                pop si
                pop dx
                pop cx
                pop bx
                pop ax
                jnc .retf
                popf
                jmp 0:0
.chainlink: equ $ - 4
.retf:
		popf
		retf

.init:
		push cs
		pop es
		mov bx, table		; es:bx -> first/default entry

		lds si, [si + irParamAddress]	; Pointer to cmd line
.irc1:           lodsb                           ; Skip over the driver name
                cmp al,9 ;tab
                je .irc2
                cmp al,' '
                je .irc2
                ja .irc1
                jmp .default
.irc2:
.irc_narg:       call irc_skip_space

                cmp al,' '                      ; Every ctrl character ends
                jb .default
		cmp al, '/'
		je .default
		cmp al, 'a'
		jb @F
		cmp al, 'z'
		ja @F
		sub al, 20h
@@:
		cmp al, 'A'
		jb .error
		cmp al, '`'
		ja .error
		cmp byte [si], ':'
		je .default
		dec si
		mov dx, si
.match:
		mov di, [es:bx + teName]
.loop:
		lodsb
		and al, ~20h
		scasb
		jne .next
		cmp byte [es:di], 0
		jne .loop
		lodsb
		cmp al, 32
		jbe .found
.next:
		mov si, dx
		add bx, TABLEENTRY_size
		cmp bx, table.end
		jb .match
.error:
		push cs
		pop ds
		mov dx, msg.error
		mov ah, 09h
		int 21h

                xor ax, ax			; NC
                lds bx, [req_ptr]
		mov [bx + irUnits],al		; Zero the number of drives
                mov word ptr [bx + irEndAddress],ax
		mov word ptr [bx + irEndAddress + 2],cs
                mov word [bx + rhStatus], DONE
		jmp .ret_NC

.found:
		dec si				; -> after matched name
		xchg si, dx			; si -> matched name, dx -> after
@@:
		mov byte [si], 32		; write a blank
		inc si
		cmp si, dx			; loop for name
		jb @B				; if si -> below the -> after name
.default:
		push cs
		pop ds
		mov cx, [bx + teAmountWords]
		mov si, [bx + tePayload]	; ds:si -> payload
		xor di, di			; es:di -> destination
		rep movsw			; place payload
		mov ax, [dhStrategy]
		mov word [.chainlink], ax
		mov word [.chainlink + 2], cs
		jmp .chain

irc_skip_space  proc near
ircs1:          lodsb
                cmp al,' '
                je ircs1
                cmp al,9 ;tab
                je ircs1
                ret
irc_skip_space  endp

msg:
.error:		db 0Dh, 0Ah, 'ReSizeable RAMDisk '
                db '(Multi)'
                db ' version ', SRD_VERSION, '. '
                db 'Copyright (c) 2005 Marko Kohtala.'
                db 0Dh, 0Ah
		ascic "RAMDisk: Invalid device driver type specified. Unloading.",13,10

%ifidni __OUTPUT_FORMAT__, obj
section STACK stack
	resb 512			; to silence linker warning
%endif
