	  .MODEL tiny
	  .CODE        ; Драйвер состоит из одного
						; сегмента кода

	  org 0        ; Эта строка может отсуствовать

	  include sysp.inc

ram  PROC far

;======================================================================

; Заголовок драйвера

	  dd   0ffffffffh       ;адрес следующего драйвера
	  dw   2000h            ;байт атрибутов
	  dw   dev_strategy     ;адрес процедуры стратегии
	  dw   dev_interrupt    ;адрес процедуры прерывания
	  db   1
	  db   7 dup(?)

bpb   equ $

	dw 512
	db 1
	dw 1
	db 2
	dw 64
	dw 360
	db 0fch
	dw 2

bpb_ptr     dw bpb

total       dw ?
verify      db 0
start_sec   dw 0
vdisk_ptr   dw 0
user_dta    dw ?
				dw ?

boot_rec equ $

	db 3 dup(0)
	db 'IBM  2.0'
	dw 512
	db 1
	dw 1
	db 2
	dw 64
	dw 360
	db 0fch
	dw 2



;======================================================================

; Программа стратегии

dev_strategy:
		mov  cs:req_seg,es
		mov  cs:req_off,bx
		ret

; Здесь запоминается адрес заголовка запроса

req_seg         dw ?
req_off         dw ?

;======================================================================

;Обработчик прерывания

dev_interrupt:
	push es     ;сохраняем регистры
	push ds
	push ax
	push bx
	push cx
	push dx
	push si
	push di
	push bp

; Устанавливаем ES:BX на заголовок запроса

	mov  ax,cs:req_seg
	mov  es,ax
	mov  bx,cs:req_off

; Получаем код команды из заголовка запроса и умножаем
; его на два, чтобы использовать в качестве индекса
; таблицы адресов обработчиков команд

	mov  al,es:[bx]+2
	shl  al,1

	sub  ah,ah            ; Обнуляем AH
	lea  di,functions     ; DI указывает на смещение таблицы
	add  di,ax            ; Добавляем смещение в таблице
	jmp  word ptr [di]    ; Переходим на адрес из таблицы

functions   LABEL  WORD  ; Таблица функций

   dw   initialize
   dw   check_media
   dw   make_bpb
   dw   ioctl_in
   dw   input_data
   dw   nondestruct_in
   dw   input_status
   dw   clear_input
   dw   output_data
   dw   output_verify
   dw   output_status
   dw   clear_output
   dw   ioctl_out
   dw   Device_open
   dw   Device_close
   dw   Removable_media

; Выход из драйвера, если функция не поддерживается

ioctl_in:
nondestruct_in:
input_status:
clear_input:
output_status:
clear_output:
ioctl_out:
Removable_media:
Device_open:
Device_close:

	or   es:word ptr [bx]+3,8103h
   jmp  quit

;======================================================================


make_bpb:

	push  es
	push  bx

	mov   cs:WORD PTR start_sec,0
	mov   cs:WORD PTR total,1
	call  calc_adr

	push  cs
	pop   es

	lea   di,bpb
	add   si,11
	mov   cx,13
	rep   movsb

	pop   bx
	pop   es

	lea   dx,bpb
	mov   es:18[bx],dx
	mov   es:20[bx],cs

	jmp  quit


check_media:

	mov   es:BYTE PTR 14[bx],1
	jmp  quit


; Обработчик команды вывода данных

output_verify:

	mov   cs:BYTE PTR verify,1

output_data:

	call  in_save
	mov   ax,es:WORD PTR 20[bx]
	mov   cs:start_sec,ax

	mov   ax,es:WORD PTR 18[bx]
	mov   cs:total,ax

	call  sector_write

	mov  es,cs:req_seg
	mov  bx,cs:req_off

	cmp   cs:BYTE PTR verify,0
	jz    no_verify

	mov   cs:BYTE PTR verify,0
	jmp   input_data

no_verify:

	jmp  quit


;======================================================================

; Обработчик команды ввода данных

input_data:

	call  in_save
	mov   ax,es:WORD PTR 20[bx]
	mov   cs:start_sec,ax

	mov   ax,es:WORD PTR 18[bx]
	mov   cs:total,ax

	call  sector_read

	mov  es,cs:req_seg
	mov  bx,cs:req_off

	jmp  quit


;======================================================================

quit:
	or   es:word ptr [bx]+3,100h
	pop bp
	pop di
	pop si
	pop dx
	pop cx
	pop bx
	pop ax
	pop ds
	pop es
   ret

;======================================================================

; Процедура выводит на экран строку
; символов в формате ASCIIZ

dpc proc near
	push si
dpc_loop:
	cmp  ds:byte ptr [si],0
	jz   end_dpc
	mov  al,ds:byte ptr [si]
	@@out_ch al
	inc si
	jmp dpc_loop

end_dpc:
	pop si
	ret
dpc endp

;======================================================================

hello db 13,10,'╔════════════════════════════════╗'
		db 13,10,'║    *RAM* (C)Frolov A., 1990    ║'
      db 13,10,'╚════════════════════════════════╝'
		db 13,10,0

;======================================================================

in_save proc near

	mov   ax,es:WORD PTR 14[bx]
	mov   cs:user_dta,ax

	mov   ax,es:WORD PTR 16[bx]
	mov   cs:user_dta+2,ax

	mov   ax,es:WORD PTR 18[bx]
	xor   ah,ah
	mov   cs:total,ax

	ret

in_save endp

calc_adr proc near

	mov   ax,cs:start_sec
	mov   cx,20h
	mul   cx

	mov   dx,cs:vdisk_ptr
	add   dx,ax
	mov   ds,dx

	xor   si,si
	mov   ax,cs:total
	mov   cx,512
	mul   cx

	or    ax,ax
	jnz   move_it

	mov   ax,0ffffh

move_it:

	xchg  cx,ax
	ret

calc_adr endp

sector_read proc near

	call  calc_adr
	mov   es,cs:user_dta+2
	mov   di,cs:user_dta

	mov   ax,di
	add   ax,cx
	jnc   read_copy
	mov   ax,0ffffh
	sub   ax,di
	mov   cx,ax
read_copy:
	rep   movsb
	ret

sector_read endp

sector_write proc near

	call  calc_adr
	push  ds
	pop   es
	mov   di,si
	mov   ds,cs:user_dta+2
	mov   si,cs:user_dta

	mov   ax,si
	add   ax,cx
	jnc   write_copy
	mov   ax,0ffffh
	sub   ax,si
	mov   cx,ax
write_copy:
	rep   movsb
	ret

sector_write endp




E_O_P:            ;Метка конца программы

initialize:

	push  cs
	pop   dx

	lea   ax,cs:vdisk
	mov   cl,4
	ror   ax,cl
	add   dx,ax
	mov   cs:vdisk_ptr,dx

	mov   ax,2d00h
	add   dx,ax

	mov   es:word ptr [bx]+14,0
	mov   es:word ptr [bx]+16,dx
	mov   es:byte ptr [bx]+13,1

	lea   dx,bpb_ptr
	mov   es:word ptr [bx]+18,dx
	mov   es:word ptr [bx]+20,cs

	mov   es,cs:vdisk_ptr
	xor   di,di
	lea   si,boot_rec
	mov   cx,24
	rep   movsb

	mov   cs:WORD PTR start_sec,1
	mov   cs:WORD PTR total,2
	call  calc_adr

	push  ds
	pop   es
	mov   di,si
	xor   al,al
	rep   stosb

	mov   ds:BYTE PTR [si],0fch
	mov   ds:BYTE PTR 1[si],0ffh
	mov   ds:BYTE PTR 2[si],0ffh

	push  ds
	push  si

	mov   cs:WORD PTR start_sec,3
	mov   cs:WORD PTR total,2
	call  calc_adr

	push  ds
	pop   es
	mov   di,si

	pop   si
	pop   ds

	rep   movsb

	mov   cs:WORD PTR start_sec,5
	mov   cs:WORD PTR total,4
	call  calc_adr

	xor   al,al
	push  ds
	pop   es
	xor   di,di
	rep   stosb


; Выводим сообщение

	mov ax,cs
	mov ds,ax
	mov si,offset hello
	call dpc

	jmp  quit

	ALIGN 16

	vdisk equ $

ram   ENDP

		  END ram
