summaryrefslogtreecommitdiffstats
path: root/private/windows/diamond/fixchg.c
blob: 61883b77bcf5561d8f38f7750f723ad7534dfccd (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
/* 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

/* ------------------------------------------------------------------------ */