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
|
/* fixchg.c */
/* Inoperative changelines frequenly cause problems when switching between */
/* 1.44Mb diskettes and 1.68Mb DMF diskettes. FixChangeline() tries to */
/* assure that drives A: and B: will not depend upon proper operation of */
/* the drive's changeline. If these efforts fail, it's no big deal; we */
/* do this without even knowing whether the changeline works or not. */
#include "fixchg.h" /* prototype verification */
/* --- definitions -------------------------------------------------------- */
/* See Microsoft MS-DOS Programmer's Reference V6.0, p.38, 312, 319 */
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
#pragma pack (1)
typedef struct
{
WORD tklSectorNum; /* this physical position's sector number */
WORD tklSectorSize; /* size of this sector in bytes */
} NUMSIZE;
typedef struct
{
WORD tklSectors; /* number of sectors in the layout */
NUMSIZE tklNumSize[1]; /* don't need much of this, not used here */
} TRACKLAYOUT;
typedef struct
{
WORD dpBytesPerSec; /* bytes per sector */
BYTE dpSecPerClust; /* sectors per cluster */
WORD dpResSectors; /* reserved sectors */
BYTE dpFATs; /* number of copies of the FAT */
WORD dpRootDirEnts; /* number of entries in the root directory */
WORD dpSectors; /* total # of sectors, 0->more than 64k */
BYTE dpMedia; /* media descriptor byte */
WORD dpFATsecs; /* sectors per copy of the FAT */
WORD dpSecPerTrack; /* sectors per track */
WORD dpHeads; /* number of heads */
DWORD dpHiddenSecs; /* sectors hidden before boot sector */
DWORD dpHugeSectors; /* number of sectors if > 64k sectors */
WORD reserved[3];
} BPB;
typedef struct
{
BYTE dpSpecFunc; /* special functions */
BYTE dpDevType; /* device type, 7=1.44Mb, 9=2.88Mb, etc. */
WORD dpDevAttr; /* device's attributes */
WORD dpCylinders; /* number of cylinders */
BYTE dpMediaType; /* media type, more like density code */
BPB dpBPB; /* the BPB (default or current) */
TRACKLAYOUT dpTrackLayout; /* track layout field appended for set call */
} DEVICEPARAMS, far *PFDEVICEPARAMS;
#pragma pack()
#define SPECIAL_GET_DEFAULT 0 /* get information for default media */
#define SPECIAL_SET_DEFAULT 4 /* set default media, good track layout */
#define ATTR_NONREMOVABLE 1 /* attr bit for non-removable device */
#define ATTR_CHANGELINE 2 /* attr bit for changeline supported */
/* --- FixChangelines() --------------------------------------------------- */
#pragma warning(disable:4704) /* no in-line balking */
void FixChangelines(void)
{
WORD dosVersion;
DEVICEPARAMS dp;
PFDEVICEPARAMS pfDp;
WORD drive;
WORD owner;
_asm mov ah,30h ; get DOS version
_asm int 21h
_asm xchg ah,al
_asm mov dosVersion,ax
/* these IoCtls were new to MS-DOS 3.2. (But then, 1.44Mb drives */
/* weren't supported until 3.3, so needing this is pretty unlikely.) */
if (dosVersion < (0x300 + 20))
{
return; /* prior versions don't need help */
}
pfDp = &dp; /* make a far pointer to DEVICEPARAMS structure */
for (drive = 1; drive <= 2; drive++) /* do A: and B: */
{
/* get drive owner so we can restore it */
_asm mov owner,0 ; assume not shared
_asm mov ax,440Eh ; Get Logical Drive Map
_asm mov bx,drive ; drive number
_asm int 21h ; execute DOS request
_asm jc no_owner ; if failed
_asm mov owner,ax ; save owner (AL)
/* set drive owner to suppress "Insert diskette for drive..." */
_asm mov ax,440Fh ; Set Logical Drive Map
_asm mov bx,drive ; drive number
_asm int 21h ; execute DOS request
/* MS-DOS 5.0 added query Ioctl, to see if the calls we need are */
/* supported. This is highly unlikely to fail. */
no_owner:
if (dosVersion >= 0x500)
{
_asm mov ax,4411h ; Query Ioctl device
_asm mov bx,drive ; drive number
_asm mov cx,0840h ; check on SET DEVICE PARAMETERS
_asm int 21h ; execute DOS request
_asm jc failed ; if not supported
_asm mov ax,4411h ; Query Ioctl device
_asm mov bx,drive ; drive number
_asm mov cx,0860h ; check on GET DEVICE PARAMETERS
_asm int 21h ; execute DOS request
_asm jc failed ; if not supported
}
/* get information about this physical device */
dp.dpSpecFunc = SPECIAL_GET_DEFAULT;
_asm push ds ; preserve data selector
_asm mov ax,440Dh ; generic IoCtl
_asm mov bx,drive ; drive number 1=A: 2=B:
_asm mov cx,0860h ; DISK / GET DEVICE PARAMETERS
_asm lds dx,pfDp ; pointer to DEVICEPARAMS structure
_asm int 21h ; execute DOS request
_asm pop ds ; restore data selector
_asm jc failed ; if error
/* is this device is removable and claims changeline is supported? */
if ((dp.dpDevAttr & (ATTR_NONREMOVABLE | ATTR_CHANGELINE)) ==
ATTR_CHANGELINE) /* if removable with changeline: */
{
/* modify device to "changeline not supported" */
dp.dpSpecFunc = SPECIAL_SET_DEFAULT;
dp.dpDevAttr &= ~ATTR_CHANGELINE; /* disable changeline */
dp.dpTrackLayout.tklSectors = 0; /* no layout being sent */
dp.dpBPB.reserved[0] = 0;
dp.dpBPB.reserved[1] = 0;
dp.dpBPB.reserved[2] = 0;
_asm push ds ; preserve data selector
_asm mov ax,440Dh ; generic IoCtl
_asm mov bx,drive ; drive number 1=A: 2=B:
_asm mov cx,0840h ; DISK / SET DEVICE PARAMETERS
_asm lds dx,pfDp ; pointer to DEVICEPARAMS structure
_asm int 21h ; execute DOS request
_asm pop ds ; restore data selector
}
failed:
/* restore initial drive owner */
_asm mov ax,440Fh ; Set Logical Drive Map
_asm mov bx,owner ; drive number
_asm or bx,bx ; is it shared?
_asm jz nextdrive ; if not shared
_asm int 21h ; execute DOS request
nextdrive:
continue; /* C labels require some statement */
}
return;
}
/* --- stand-alone test stub ---------------------------------------------- */
#ifdef STANDALONE
void main(void)
{
FixChangelines();
}
#endif
/* ------------------------------------------------------------------------ */
|