summaryrefslogtreecommitdiff
path: root/v4.0/src/BIOS/MSVOLID.INC
blob: d1a958812e61596fbe6b86c6b27082c669ae3161 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
;-------------------------------------------------------------------------
;
;  File: msvolid.asm
;	This file contains the volume_id subroutines and data structures.
;
;	Routines in this file are:
;	   Set_Volume_ID       -	main routine, calls other routines.
;	   read_volume_id      -	read the volume ID and tells if it has
;					   been changed.
;	   Transfer_volume_id  -	copy the volume ID from TMP to special
;					   drive.
;	   Check_Volume_ID     -	compare volume ID in TMP area with one
;					   expected for drive.
;	   Fat_Check	       -	see of the fatID has changed in the
;					   specified drive.
;	   Init_Vid_loop       -	set up for VID scan or move
;
;
;-------------------------------------------------------------------------

;
; length of the volume id
;

vid_size    equ 12

	    PATHSTART 001,VOLID 					  ;3.30

;
; null volume id
;

nul_vid db  "NO NAME    ",0

;
; data scratch area used to hold volume ids
;

tmp_vid db  "NO NAME    ",0

	    PATHEND 001,VOLID						  ;3.30

;
; Set_Volume_ID
;   If drive has changeline support, read in and set the volume_ID
; and the last FAT_ID byte.  If no change line support then do nothing.
;
;   On entry:
;	DS:DI points to the BDS for this disk.
;	AH contains media byte
;
;   On Exit:
;	Carry clear:
;	   Successful call
;	Carry set
;	   Error and AX has error code
;

Set_Volume_ID:
	PUBLIC SET_VOLUME_ID						  ;3.30
	push	dx			; save registers
	push	ax
	CALL	HasChange		; does drive have changeline support?
	jz	setvret 		; no, get out
	push	di
	call	read_volume_ID		; read the volume ID
	pop	di
	jc	SetErr			; if error go to error routine
	call	transfer_volume_ID	; copy the volume id to special drive
	call	ResetChanged		; restore value of change line

setvret:				; SET Volume RETurn
	clc				; no error, clear carry flag
	pop	ax			; restore registers
	pop	dx
	ret
SetErr:
	pop	dx			; pop stack but don't overwrite AX
	pop	dx			; restore DX
	ret



root_sec	DW	?	;Root sector #




;
; read_volume_id read the volume ID and tells if it has been changed.
;
;   On entry:
;	DS:DI points to current BDS for drive.
;   On Exit:
;	Carry Clear
;	    SI = 1  No change
;	    SI = 0  ?
;	    SI = -1 Change
;
;	Carry Set:
;	    Error and AX has error code.
;

read_volume_id:
	push	ES			; preserve registers
	push	DX
	push	CX
	push	BX
	push	AX
	push	DS			; Preserve Current BDS
	push	DI
	push	cs			; get ES segment correct
	pop	es
	push	cs			; get DS segment correct
	pop	ds
	mov	di,offset tmp_vid
	mov	si,offset nul_vid
	mov	cx,vid_size
	rep	movsb			; initialize tmp_vid to null vi_id

	pop	DI			; Restore Current BDS
	pop	DS
	mov	al,byte ptr ds:[di].cFAT    ; # of fats
	mov	cx,word ptr ds:[di].csecfat ; sectors / fat
	mul	cl			    ; size taken by fats
	add	ax,word ptr ds:[di].ressec  ; add on reserved sectors
					; AX is now sector # (0 based)
	mov	cs:[root_sec],ax	; set initial value
	mov	ax,[di].cDir		; # root dir entries
	mov	cl,4			; 16 entries/sector
	shr	ax,cl			; divide by 16
	mov	cx,ax			; cx is # of sectors to scan
next_sec:
	push	cx			; save outer loop counter
	mov	ax,cs:[root_sec]	; get sector #
	mov	cx,word ptr ds:[di].seclim    ; sectors / track
	xor	DX,DX
	div	cx
			; set up registers for call to read_sector
	inc	DX		; dx= sectors into track, ax= track count from 0
	mov	cl,dl		; sector to read
	xor	DX,DX
	div	word ptr ds:[di].hdlim ; # heads on this disc
	mov	dh,dl		; Head number
	mov	ch,al		; Track #
	call	read_sector	; get first sector of the root directory,
				; ES:BX -> BOOT
	jc	ReadVIDErr	; error on read
	mov	cx,16		; # of dir entries in a block of root
	mov	al,08h		; volume label bit
fvid_loop:
	cmp	byte ptr es:[bx],0	; End of dir?
	jz	no_vid			; yes, no vol id
	cmp	byte ptr es:[bx],0E5h	; empty entry?
	jz	ent_loop		; yes, skip
	test	es:[bx+11],al		; is volume label bit set in fcb?
	jnz	found_vid		; jmp yes
ent_loop:
	ADD	BX,32		;MJB003 ADD LENGTH OF DIRECTORY ENTRY	  ;3.30
	loop	fvid_loop
	pop	cx			; outer loop
	inc	cs:[root_sec]		; next sector
	loop	next_sec		; continue
NotFound:
	XOR	SI,SI
	jmp	short fvid_ret

found_vid:
	pop	cx			; clean stack of outer loop counter
	mov	si,bx			; point to volume_id
	push	ds			; preserve currnet BDS
	push	di
	push	es			; es:si points to volume id.
	pop	ds			; source segment
	push	cs
	pop	es			; destination segment
	mov	di,offset tmp_vid	; dest of volume_id
	mov	cx,vid_size -1		; length of string minus NUL
	rep	movsb			; mov volume label to tmp_vid
	xor	al,al
	stosb				; Null terminate
	XOR	SI,SI
	pop	DI			; restore current BDS
	pop	DS
fvid_ret:
	pop	ax
	clc
RVIDRet:
	pop	BX			; restore register
	pop	CX
	pop	DX
	pop	ES
	ret
no_vid:
	pop	cx			; clean stack of outer loop counter
	jmp	NotFound		; not found
ReadVIDErr:
	pop	SI
	pop	SI
	jmp	RVIDRet



;
;   Transfer_volume_id - copy the volume ID from TMP to special drive
;
;   Inputs:	DS:DI nas current BDS
;   Outputs:	BDS for drive has volume ID from TMP
;

transfer_volume_ID:
	push	DS		; preserve current BDS
	push	DI
	push	ES
	push	SI
	push	CX
	call	init_vid_loop
	cld
	rep	MOVSB		; transfer
	pop	CX
	pop	SI
	pop	ES
	pop	DI		; restore current BDS
	pop	DS
	ret


;
;   Check_Volume_ID - compare volume ID in TMP area with one expected for
;	drive
;
;   Inputs:	DS:DI has current BDS for drive
;   Outputs:	SI = 0 if compare succeeds
;		SI = -1 if compare fails.

check_volume_id:
	push	DS			; preserve current BDS for drive
	push	DI
	push	ES
	push	CX
	call	init_vid_loop
	cld
	repz	cmpsb			; are the 2 volume_ids the same?
	mov	si,0			; assume unknown
	jz	check_vid_ret		; carry clear if jump taken
	mov	si,-1			; failure
check_vid_ret:
	pop	CX
	pop	ES
	pop	DI			; restore current BDS
	pop	DS
	ret

;
;   Fat_Check - see of the fatID has changed in the specified drive.
;	      - uses the FAT ID obtained from the boot sector.
;
;   Inputs:	MedByt is expected FAT ID
;		DS:DI points to current BDS
;   Output:	Carry Clear
;		    SI = -1 if fat ID different,
;		    SI = 0 otherwise
;   No other registers changed.

FAT_CHECK:
	push	AX
	xor	SI, SI			 ; say FAT ID's are same.
	mov	AL, cs:MedByt
	cmp	AL, byte ptr [DI].Mediad ; compare it with the BDS medbyte
	jz	OKRET1			 ; carry clear
	dec	SI
OkRet1: clc
	pop	AX
	ret


;
;   Init_Vid_loop - set up for VID scan or move
;
;   Inputs:	DS:DI pionts to BDS for the drive
;   Outputs:	DS:SI points to tmp_vid
;		ES:DI points to vid for drive
;		CX has size for VID compare
;

init_vid_loop:
	push	ax
	push	ds
	pop	es
	push	cs
	pop	ds
	mov	si,offset tmp_vid   ; source
	add	di,volid
	mov	cx,vid_size
	pop	ax
	ret