;	       Резидентная часть драйвера винчестера
;                       с загрузчиком
;                =================================
; 	        *** Written by Oleg H. apr 1996 ***

	.TITLE	HDD-disk resident
	.LIST	TTM
	.DSABL	GBL
	.ENABL	LC

;╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣
	.Psect	Code
	.Psect	Proc
	.Psect	PPsbio
	.Psect	PP.Res
	.Psect	PP.Ins
	.Psect	RelTab
RelTab::
	.Psect	EndTab
EndRel::
	.Psect	Data
	.Psect	Text,d
	.Psect	Empty
;╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣
.macro mput    adrmp

          jsr     r2,mput$
          .word   adrmp
.endm

.macro rel     cmd,a1,a2,?local

    .if   idn     <cmd>,.word
     $'local ==:.
          .word   a1
    .iff
     $'local ==:.+2
      .if   b     <a2>
          cmd     a1
      .iff
          cmd     a1,a2
      .endc
     .endc
          .save
          .psect  reltab
          .word   $'local
          .restore
.endm
.macro .Exit
	clr	pc
.endm

.macro .Print	msg
 .if nb,<msg>
	jsr	r5,Prnt$1
	.word	msg
 .iff
	jsr	r5,Prnt$2
 .endc
.endm

;╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣
	WD$csr = 176670
	WD$vec = 144
	pw$vec = 24
	rsk2   = 176674
	rdk2   = 176676
	keyprc = 111144
	dprc0  = 174152
	disp   = 174164
	rap    = 177010
	rdp    = 177014
	WD$reg = 177054
	sysreg = 177716
	casadr = 32		; 26		; with 600 !
	PASWRD = 342
	ADRPRC = 7126		; Процесс рестарта
	PPBase = 1200-<I$1200-InsBeg>	; 1100
	NPart  = 8.
	WD$cqe = <1022-1010>/2
	DefBot = 120
	DefTim = 122
;╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣
	.Psect	code

start:
	mov	#10000,sp
	mtps	(pc)
	Reset
	Call	SetRes
	bcs	100$
	Call	Boot.M
	emt	350
100$:
	.Exit
;╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣
Boot.M:
	Mput	Lo$SB
	mov	#SbBuf,r2
	tst	(r2)+		; А суперблок уже загружен?
	bne	1$
	Call	sb$r
1$:	
	Call	sb.tst			; mov sbbuf,r1
	beq	5$
	.Print	Pref2
	.Print	SbCRC
5$:	
	tst	(r2)+
	beq	10$
	incb	Max.PN
	br	5$
10$:	bic	#^c7,DefBot(r1)
	bisb	DefBot(r1),Cur.PN
	.print	Q.Part
	mov	#100,r2
	mov	(r2),-(sp)
	mov	#Tim$lc,(r2)
15$:
	mov	DefTim(r1),Tim$w
16$:	tst	Tim$w
	ble	20$
17$:	tstb	@#177560
	bpl	16$
	movb	@#177562,r0
	cmpb	r0,#177			; переписать суперблок безусловно
	beq	18$
	cmpb	r0,#15			; Не дожидаясь тайм-аута - default
	beq	20$
	cmpb	r0,#'0
	blo	15$
	cmpb	r0,Max.PN
	bhi	15$
	cmpb	r0,Cur.PN		; Если тот же раздел - не писать
	beq	20$
	movb	r0,Cur.PN
	movb	r0,DefBot(r1)
18$:	call	Sb.clc			; mov sbbuf,r1
	Call	sb$w			; write superblock
20$:	
	mov	(sp)+,(r2)		; @#100
	.Print	Cur.PN
	.print	CrLfLf
	movb	Cur.PN,r0
	bicb	#^c7,r0			; Номер привода
	mov	r0,SbRead+3
	call	Read.0			; Читаем 0 блок
	bne	B0$Err

	asl	r2			; 100 -> 200
	mtps	r2			; #200
	clr	r3
40$:
	mov	(r1)+,(r3)+
	mov	(r1)+,(r3)+
	sob	r2,40$
 	mtps	r2
	clr	pc			; Пуск начального загрузчика
B0$Err:
	.Print	Pref2
	.Print	BL$Err
	Return
;╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣
SetRes:
	.Print	prefix
	Mput	Lo$Ins
	Mput	Ex$Ins
WaiTes = :.+2
1$:	mov	#-1,r5
	bmi	1$
	beq	LoadPP
	mov	#Alread,r0
	asr	r5
	bcc	R.good
	mov	#NoDev,r0

R.bad:	.print
	sec
	return

R.good:	.print
	return

LoadPP:
	Call	Read.0			; Читаем суперблок
	bne	Sb$Err

	Call	sb.tst			; mov sbbuf,r1
	beq	5$
	.Print	SbCRC
5$:	clr	r0
	bisb	(r1)+,r0
	mov	r0,Spt
		
	clr	r3
	bisb	(r1)+,r3
	mul	r0,r3
	mov	r3,SptHed

	MOV	R2$ADR,R0	; Релокация единственной точки
	SUB	#R$BEG,R0
	ADD	R0,@RELTAB
	
	mov	#DevTab,r0
	clr	r2
	inc	r2
	clr	r3
10$:
	mov	r3,(r0)+
	mov	r2,(r0)+
	add	(r1)+,r2
	adc	r3
	cmp	r0,#E$Dtab
	blo	10$

	mput	res$2

	mov	#Succes,r0
	br	r.good
Sb$Err:	
	mov	#Sbioer,r0
	br	r.bad

;╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣
	.Psect	Text
Prefix:	.asciz	<15>/?WDR-/
Pref2:	.asciz	<15>/?WDB-/
BL$Err:	.asciz	/F-Ошибка чтения нулевого блока раздела/<15><12>
Alread:	.asciz	/I-Резидент уже загружен/<15><12>
Succes:	.asciz	/I-Резидент загружен успешно/<15><12>
NoDev:	.ascii	/F-Нет контроллера НЖМД/
CrLfLf:	.byte	15,12,12,0
Sbioer:	.asciz	/F-Ошибка чтения суперблока/<15><12>
SbCRC:	.asciz	/W-Ошибка контрольной суммы/<15><12>
Q.part:	.ascii	<12><15>/Номер boot-раздела (0-/
Max.PN:	.byte	'0-1
	.ascii	/): /<033><244>
Cur.PN:	.asciz	/0/<10><033><277><244>

;╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣
	.Psect	proc
MPut$:
	call	5$		;  Подождем готовности К2
1$:	call	4$		;  Вытолкнем в К2 первые 2 байта адрес
	clrb	@-(r2)		;  Очистим байт ответа
	jsr	r2,3$		;  Передадим 2 байта завершения 377
	.word	-1		;
	tstb	@(r2)+		;  Проверим ответ
2$:	rts	r2		;  Выйдем в основную программу
3$:	push	#2$		; 
4$:	push	pc		;  Обеспечим повторный вход
	movb	(r2)+,@#rdk2	;  Передача байта в К2
5$:	tstb	@#rsk2		;  Ожидание готовности К2
	bpl	5$		;
	return			;  выход

Prnt$1:
	mov	(r5)+,r0
Prnt$2:
1$:	tstb	@#177564
	bpl	1$
	movb	(r0)+,@#177566
	bne	1$
	rts	r5

Sb.Tst:
	jsr	r2,crcclc
	.word	377
	add	(r3),r5
	bis	r4,r5
	Return
Sb.clc:
	jsr	r2,crcclc
	.word	376
	inc	r5
	neg	r4
	neg	r5
	mov	r4,(r3)+
	mov	r5,(r3)
	Return
crcclc:
	mov	(r2)+,r0
	mov	#SbBuf,r1
	mov	r1,r3
	clr	r4
	clr	r5
2$:	add	(r3)+,r4
	adc	r5
	sob	r0,2$
	Rts	r2

SB$R:
	mov	#-1,sb$WF
	Mput	Ex$SBR
	br	$comon
SB$W:
	mov	#-1,sb$WF
	Mput	Ex$SBW
$comon:	tst	(pc)+
sb$WF:	.blkw	1
	bmi	$comon
	return
Read.0:
	mov	#Sb$Lc,@#WD$vec		; Читаем 0-блок
	mov	#paswrd,@#WD$vec+2
1$:	tstb	@#WD$vec+2
	bmi	1$
	Return
;╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣
	.Psect	pp.ins
InsBeg:
	mov	#4,r5
	jsr	r4,1$
				; Процедура обработки trap4
	add	#2,(sp)		; Перескок, если было прерывание
	rti
1$:	mov	(r5),(sp)	; Сохраним старое знач. вектора 4
	mov	r4,(r5)+	; Захватим вектор 4
	mov	@#casadr,r2	; А резидент уже был загружен ? (r5 == 6)
	bne	reexit		; -да, уже был - сообщим в ЦП  (addr)
	mov	#WD$reg,r3
	push	(r3)
	mov	(pc),r1		; 106407
	mtps	pc		; Это круто !!!
I$1200:	mov	r5,(r3)		; (6) для загрузки WD$reg
				; r4 > 0, мл. бит == 0 
	tstb	-(r1)		; 106406
	br	casfnd
 	mov	#16,r5		; (16) для загрузки WD$reg
 	mov	r5,(r3)		; 
	tstb	(r1)		; 106406
	br	casfnd
	comb	r4		; Кассеты нет - мл. бит == 1
exitin:	pop	(r3)
	mtps	r2		; #0
reexit:	mov	(sp)+,@#4	; Освободим вектор 4
	mov	#WaiTes/2,@#Rap
	mov	r4,@#Rdp
ret..:	return

; вернуть: r2 == 0, r4 - мл. бит == 0
casfnd:
	movb	r5,@#CasAdr	; Установим No кассеты для резидента

	mov	#Rap,r4

	mov	#R$end-R$beg,r0
	Call	@#176132	; Getmem(); r0 - size, r1 - pointer

	mov	#R2$adr/2,(r4)	; Передадим в ЦП адрес загрузки резидента
	mov	r1,@#Rdp	; для его обновления
	
	mov	#R$beg/2,(r4)	; 
	Asr	r0
	jsr	r5,@#125602	; Copy resident...
	; r1 указывает на буфер за конец резидента
	Sub	#R$end,r1	; Дельта перемещения
.REM %
	mov	#RelTab/2,(r4)
10$:	mov	@#Rdp,r0
	add	r1,r0
	add	r1,(r0)
	inc	(r4)
	Dec	#<EndRel-RelTab>/2
	bne	10$
%
	mov	#RelTab/2,(r4)
	mov	@#Rdp,r0
	add	r1,r0
	add	r1,(r0)
	
	mov	@#adrprc,r0	; Адрес 
	bmi	1$
	mov	r0,jmpadr(r1)
	mov	#jmpadr/2,(r4)
	mov	r0,@#Rdp
1$:	add	#S$beg,r1	; Адрес входа в резидент
	mov	r1,@#adrprc

	clr	r4
	br	exitin
InsEnd:
;╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣
	.Psect	PPsbio
sb.rw:
Sb.W:
	jsr	r3,sbcomm
	mov	@(pc)+,(r3)
	.word	177717
Sb.R:
	jsr	r3,sbcomm
	mov	(r3),@(pc)+
	.word	177737
Sbcomm:
	tst	(sp)+

	call	int.d
1$:
	call	int...
	tstb	@#110000
	bpl	1$			; Device BUSY

	mov	#110014,r4
10$:
	mov	Sb.Tab-Sb.rw+PPbase-110014-2(r4),-(r4)
	bmi	10$

	mov	(r3)+,Sb.Cmd		; Команда пиши/читай
	mov	(r3)+,-(r4)		; КОП в винчестер
	Mov	#400,R0			; 400 - размер блока
20$:
	call	int...
	movb	(r4),r1
	bpl	20$			; BSY
	asr	r1
	bcc	sbIerr
	bic	#^c50,r1
	bne	20$

	mov	#110016,r3
	mov	#SbBuf/2,@#Rap

sb.cmd:	.blkw	1
	.word	Rdp
	inc	@#Rap
	sob	r0,sb.cmd
sbIerr:				;///////////
	mov	#sb$WF/2,@#rap
	mov	r0,@#Rdp	; 0 - if OK; 400 - if error	
int.e:
	mov	O$WD$R,@#WD$reg
	mtps	#0
	return

Int...:	call	int.e
int.d:
O$WD$R = :.+4
	mov	@#WD$reg,#0		; Сохраним старое состояние
	mtps	(pc)
	mov	@#CasAdr,@#WD$reg	; И подключим СПЗУ
	return
	
	;	110002		110004	110006	110010	110012
	;	s:d:h		trk-hi	trk-lo	sct	Nsct
	.word	<^c100> & 377,	^c0,	^c0,	^c1,	^c1
Sb.Tab:
	.Even
sb.rw.e:
;╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣
	.Psect	pp.res

R$beg:	.rad50	/WD SYS/
S$beg:
	mtps	(pc)			; Загрузим PSW == 304
	mov	#rap,r4
	mov	#rdp,r5
	mov	r1,-(sp)
	mov	@#WD$reg,-(sp)		; Сохраним старое состояние
	mov	@#CasAdr,@#WD$reg	; И подключим СПЗУ
	tstb	@#110000
	bpl	PL.nop			; Device BUSY
	mov	(pc)+,r2
wcnt:	.word	0
	bgt	common			; Еще чего-то надо доделать

	mov	#<WD$vec/2>+1,(r4)	; Указывает на PSW в векторе ЦМ
	cmp	#paswrd,(r5)
	bne	NE.nop			; Пустой вызов - выйти
1$:
	clr	RetCod			; Код возврата установим в 0
				; ** Извлечение из ЦП параметров
	dec	(r4)			; Указатель на WDint
	mov	(r5),(r4)
	ror	(r4)
	sub	#WD$cqe,(r4)		; Указатель на WDcqe
	mov	(r5),(r4)
	ror	(r4)			; Указатель на элемент очереди

	mov	(r5),r3			; Номер блока
	inc	(r4)
	mov	(r5),r1			; Номер устройства в ст. байте
	inc	(r4)			; Теперь указывает на @буфер
	push	r1
10$:
	clrb	r1
	ash	#-6,r1			; -8 + 2 - смещ. в таблице
rel	add	#DevTab,r1		; Указ. на DevTab (ст. слово)
	mov	(r1)+,r2

	mov	4(r1),r0
	sub	(r1),r0			; Размер раздела (партиции)

	cmpb	(sp)+,#373		; Spfun "SIZE" ?
	bne	20$
					; Обработка SpFun_373
	mov	(r5),(r4)
	ror	(r4)
	mov	r0,(r5)
	br	exit0
20$:
	sub	r3,r0			; Сколько блоков еще можно читать 
					; из этого раздела
	blo	E.bad			; Нельзя за границу раздела !!!

	add	(r1),r3			; R2,R3 - 32-х разрядный абсолютный
	adc	r2			; номер блока на винчестере

SPTHED = :.+2
	div	#1,r2
	mov	#110006,r1
	com	r2
	mov	r2,(r1)			; Дорожка мл
	swab	r2
	mov	r2,-(r1)		; Дорожка ст
	clr	r2
SPT    = :.+2
	div	#1,r2
	bis	#100,r2			; Размер сектора-512
	com	r2
	com	r3
	sbc	r3

	mov	r2,-(r1)		; Поверхность
	mov	r3,@#110010		; Сектор
	mov	(r5),buff		; Buffer
	ror	buff

	jsr	r5,Set$RW		; ёУстановим режим чтения
	mov	(r3),(r5)		; ╥
	tst	(r3)			; ╥
	.word	177737			; ╧

	inc	(r4)
	mov	(r5),r2			; Количество слов
	beq	exit0
	bpl	1$
	neg	r2
	jsr	r5,Set$RW		; ёУстановим режим записи
	mov	(r5),(r3)		; ╥
	clr	(r3)			; ╥
	.word	177717			; ╧
1$:
	mov	r2,r3
	add	#377,r3
	clrb	r3
	swab	r3			; Сколько блоков читать (мл. байт)

	cmp	r3,r0
	blos	10$
	mov	r0,r3

10$:	com	r3
	mov	r3,@#110012		; Кол-во секторов
	mov	r1,@#110000		; Старт операции
	mov	r2,wcnt
Common:
	mov	(pc)+,(r4)
buff:	.blkw	1
	mov	#110016,r3
next$b:
	movb	@#110000,r1
PL.nop:	bpl	ex.nop		; BSY
	asr	r1
	bcs	10$
E.bad = .			; I/O ERROR
	inc	RetCod
	br	exit0
10$:	bic	#^c50,r1
NE.nop:	bne	ex.nop

	Mov	#400,R0		; 400 - размер блока 
	sub	r0,r2
	bge	copy
	add	r2,r0
copy:
	Add	#3,r0
	ashc	#-2,r0
	ashc	#-14,r1
	sub	#14,r1
	sub	r1,pc
cmd1:	.blkw	1
	inc	(r4)
cmd2:	.blkw	1
	inc	(r4)
cmd3:	.blkw	1
	inc	(r4)
cmd4:	.blkw	1
	inc	(r4)
	sob	r0,cmd1

	mov	(r4),buff
	mov	r2,wcnt
	bgt	common
	beq	exit0
	inc	pc			; Флаг - надо доделать операцию
exit0:
	mov	#<WD$vec/2>+1,(r4)
RetCod = :.+2
	mov	#0,(r5)			; Код ошибки
	dec	(r4)
	mov	(r5),r0			; Вектор прерывания
	mov	#pw$vec/2,(r4)
	mov	(r5),r1
	mov	r0,(r5)			; Указатель на WD$int
	bic	#100000,@#sysreg	; Прерывание в ЦМ
	bis	#100000,@#sysreg	; Прерывание в ЦМ
	mov	r1,(r5)

	inc	pc
	br	ex.nop			; Если ничего доделывать не надо
cmd5:	.blkw	1
	inc	wcnt
	bmi	cmd5
ex.nop:	
	mov	(sp)+,@#WD$reg
	mov	(sp)+,r1
	mov	r1,@#adrprc		; Занесем адрес первого процесса
	mtps	(pc)			; Загрузим PSW == 117
	jmp	@(pc)+
jmpadr:	.word	disp			; Вернемся в диспетчер

Set$RW:
	mov	(r5),Cmd1
	mov	(r5),Cmd2
	mov	(r5),Cmd3
	mov	(r5)+,Cmd4
	mov	(r5)+,Cmd5
	mov	(r5)+,r1
	Rts	r5
DevTab:
	.Word	0,0
	.Word	0,1
;	.Blkw	2*7.
;
;E$Dtab:
;R$end:
E$Dtab	== : DevTab + <4*9.>
R$end	= : DevTab + <4*9.>

;╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣
	.Psect	data

Lo$Ins:	.byte	0,20,32,0		; Запись инсталлятора
	.word	PPBase
	.Word	InsBeg,<InsEnd-InsBeg>/2

Lo$SB:	.byte	0,20,32,0		;
	.word	PPBase
	.Word	Sb.RW,<Sb.RW.e-Sb.RW>/2

Res$2:	.byte	0,20,32,0		; Запись 2-й копии резидента
R2$adr:	.word	0
	.Word	R$Beg,<R$End-R$Beg>/2

Ex$Ins:	.byte	0,30,32,0		; Запуск инсталлятора
	.word	PPBase

Ex$SbR:	.byte	0,30,32,0		; Чтение суперблока
	.word	PPBase+Sb.R-Sb.RW
Ex$SbW:	.byte	0,30,32,0		; Запись суперблока
	.word	PPBase+Sb.W-Sb.RW


SbRead:	.word	0			; Q$blkn
	.word	0			; Q$func ! Q$unit
	.word	SbBuf			; Q$buff
	.word	400			; Q$wcnt
	.Word	SbRead			; ...CQE
	.blkw	WD$Cqe-3
Tim$lc:	dec	(pc)+
Tim$w:	.word	10.
Sb$Lc:	Rti

;╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣╣
	.Psect	Empty
SbBuf::	.word	0

	.END	start
                                                                                                                                                                          