Skip to content

Commit ff933de

Browse files
ecm-pushbxPerditionC
authored andcommitted
sys.c: work around Xi8088 ROM-BIOS bug for int 13.41 [#156]
This commit contains a number of changes: 1. int86x gets and sets struct SREGS members ds and es 2. int86x patches itself (SMC) using a cs: segment override prefix, as ds may no longer equal cs. 3. int86x interrupt number is %7 rather than %5 4. int86x assembly part doesn't push and pop ds, it is handled by the compiler instead (in practice it puts a push ss \ pop ds at the end of the function to restore the near data segment). 5. int86 is implemented by calling int86x (with ds = es = 0) 6. findfirst, int2526readwrite, fat32readwrite also changed to use int86x because they need to set ds. This used to be implied as the same ds that the compiler already used by default. 7. Finally, haveLBA changed to set ds to 40h. The inline assembly constraints for gcc-ia16 are documented in https://gitlab.com/tkchia/gcc-ia16/-/blob/ca893320926dc93552390b892a202e9373d040c0/gcc/doc/md.texi#L2379
1 parent 86db573 commit ff933de

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

sys/sys.c

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -105,24 +105,34 @@ struct _diskfree_t {
105105
unsigned short avail_clusters, sectors_per_cluster, bytes_per_sector;
106106
};
107107

108-
int int86(int ivec, union REGS *in, union REGS *out)
108+
int int86x(int ivec, union REGS *in, union REGS *out, struct SREGS *s)
109109
{
110110
/* must save sp for int25/26 */
111-
asm("mov %5, (1f+1); jmp 0f; 0:push %%ds; mov %%di, %%dx; mov %%sp, %%di;"
111+
asm("mov %7, %%cs:(1f+1); jmp 0f; 0:"
112+
"mov %%di, %%dx; mov %%sp, %%di;"
112113
"push %%di; push %%di;"
113114
/* push twice to work both for int 25h/26h and int 21h */
114115
"1:int $0x00; pop %%di; pop %%di;"
115116
/* second pop always reads the correct SP value.
116117
the first pop may read the FL left on stack. */
117-
"mov %%di, %%sp; pop %%ds; sbb %0, %0" :
118+
"mov %%di, %%sp; sbb %0, %0" :
118119
"=r"(out->x.cflag),
119-
"=a"(out->x.ax), "=b"(out->x.bx), "=c"(out->x.cx), "=d"(out->x.dx) :
120+
"=a"(out->x.ax), "=b"(out->x.bx), "=c"(out->x.cx), "=d"(out->x.dx),
121+
"=e"(s->es), "=Rds"(s->ds) :
120122
"q"((unsigned char)ivec), "a"(in->x.ax), "b"(in->x.bx),
121-
"c"(in->x.cx), "D"(in->x.dx), "S"(in->x.si) :
123+
"c"(in->x.cx), "D"(in->x.dx), "S"(in->x.si), "e"(s->es),
124+
"Rds"(s->ds)
125+
:
122126
"cc", "memory");
123127
return out->x.ax;
124128
}
125129

130+
int int86(int ivec, union REGS *in, union REGS *out)
131+
{
132+
struct SREGS sr = {0,};
133+
return int86x(ivec, in, out, &sr);
134+
}
135+
126136
int intdos(union REGS *in, union REGS *out)
127137
{
128138
return int86(0x21, in, out);
@@ -205,7 +215,8 @@ int _dos_findfirst(const char *file_name, unsigned int attr,
205215
in.h.ah = 0x4e;
206216
in.x.dx = FP_OFF(file_name);
207217
in.x.cx = attr;
208-
intdos(&in, &out);
218+
sr.ds = FP_SEG(file_name);
219+
intdosx(&in, &out, &sr);
209220
if (out.x.cflag)
210221
return out.x.ax;
211222
/* memcpy(find_tbuf, (void *)0x80, sizeof(*find_tbuf)); */
@@ -1140,12 +1151,14 @@ int generic_block_ioctl(unsigned drive, unsigned cx, unsigned char *par);
11401151
int int2526readwrite(int DosDrive, void *diskReadPacket, unsigned intno)
11411152
{
11421153
union REGS regs;
1154+
struct SREGS sregs;
11431155

11441156
regs.h.al = (BYTE) DosDrive;
11451157
regs.x.bx = (short)diskReadPacket;
11461158
regs.x.cx = 0xffff;
1159+
sregs.ds = FP_SEG(diskReadPacket);
11471160

1148-
int86(intno, &regs, &regs);
1161+
int86x(intno, &regs, &regs, &sregs);
11491162

11501163
return regs.x.cflag;
11511164
}
@@ -1161,13 +1174,15 @@ int2526readwrite(DosDrive, diskReadPacket, 0x26)
11611174
int fat32readwrite(int DosDrive, void *diskReadPacket, unsigned intno)
11621175
{
11631176
union REGS regs;
1177+
struct SREGS sregs;
11641178

11651179
regs.x.ax = 0x7305;
11661180
regs.h.dl = DosDrive;
11671181
regs.x.bx = (short)diskReadPacket;
11681182
regs.x.cx = 0xffff;
11691183
regs.x.si = intno;
1170-
intdos(&regs, &regs);
1184+
sregs.ds = FP_SEG(diskReadPacket);
1185+
int86x(0x21, &regs, &regs, &sregs);
11711186

11721187
return regs.x.cflag;
11731188
} /* fat32readwrite */
@@ -1292,10 +1307,15 @@ BOOL haveLBA(void); /* return TRUE if we have LBA BIOS, FALSE otherwise */
12921307
BOOL haveLBA(void)
12931308
{
12941309
union REGS r;
1310+
struct SREGS sr;
12951311
r.x.ax = 0x4100;
12961312
r.x.bx = 0x55AA;
12971313
r.h.dl = 0x80;
1298-
int86(0x13, &r, &r);
1314+
sr.ds = 0x40;
1315+
/* ds = 40h is to work around a Xi8088 ROM-BIOS bug,
1316+
refer to https://github.com/FDOS/kernel/issues/156
1317+
and https://www.bttr-software.de/forum/forum_entry.php?id=21275 */
1318+
int86x(0x13, &r, &r, &sr);
12991319
return r.x.bx == 0xAA55 && r.x.cx & 1;
13001320
}
13011321
#endif

0 commit comments

Comments
 (0)