mirror of
https://github.com/FDOS/kernel.git
synced 2025-12-10 22:50:31 +01:00
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
ca89332092/gcc/doc/md.texi (L2379)
This commit is contained in:
parent
86db573347
commit
ff933ded1f
38
sys/sys.c
38
sys/sys.c
@ -105,24 +105,34 @@ struct _diskfree_t {
|
||||
unsigned short avail_clusters, sectors_per_cluster, bytes_per_sector;
|
||||
};
|
||||
|
||||
int int86(int ivec, union REGS *in, union REGS *out)
|
||||
int int86x(int ivec, union REGS *in, union REGS *out, struct SREGS *s)
|
||||
{
|
||||
/* must save sp for int25/26 */
|
||||
asm("mov %5, (1f+1); jmp 0f; 0:push %%ds; mov %%di, %%dx; mov %%sp, %%di;"
|
||||
asm("mov %7, %%cs:(1f+1); jmp 0f; 0:"
|
||||
"mov %%di, %%dx; mov %%sp, %%di;"
|
||||
"push %%di; push %%di;"
|
||||
/* push twice to work both for int 25h/26h and int 21h */
|
||||
"1:int $0x00; pop %%di; pop %%di;"
|
||||
/* second pop always reads the correct SP value.
|
||||
the first pop may read the FL left on stack. */
|
||||
"mov %%di, %%sp; pop %%ds; sbb %0, %0" :
|
||||
"mov %%di, %%sp; sbb %0, %0" :
|
||||
"=r"(out->x.cflag),
|
||||
"=a"(out->x.ax), "=b"(out->x.bx), "=c"(out->x.cx), "=d"(out->x.dx) :
|
||||
"=a"(out->x.ax), "=b"(out->x.bx), "=c"(out->x.cx), "=d"(out->x.dx),
|
||||
"=e"(s->es), "=Rds"(s->ds) :
|
||||
"q"((unsigned char)ivec), "a"(in->x.ax), "b"(in->x.bx),
|
||||
"c"(in->x.cx), "D"(in->x.dx), "S"(in->x.si) :
|
||||
"c"(in->x.cx), "D"(in->x.dx), "S"(in->x.si), "e"(s->es),
|
||||
"Rds"(s->ds)
|
||||
:
|
||||
"cc", "memory");
|
||||
return out->x.ax;
|
||||
}
|
||||
|
||||
int int86(int ivec, union REGS *in, union REGS *out)
|
||||
{
|
||||
struct SREGS sr = {0,};
|
||||
return int86x(ivec, in, out, &sr);
|
||||
}
|
||||
|
||||
int intdos(union REGS *in, union REGS *out)
|
||||
{
|
||||
return int86(0x21, in, out);
|
||||
@ -205,7 +215,8 @@ int _dos_findfirst(const char *file_name, unsigned int attr,
|
||||
in.h.ah = 0x4e;
|
||||
in.x.dx = FP_OFF(file_name);
|
||||
in.x.cx = attr;
|
||||
intdos(&in, &out);
|
||||
sr.ds = FP_SEG(file_name);
|
||||
intdosx(&in, &out, &sr);
|
||||
if (out.x.cflag)
|
||||
return out.x.ax;
|
||||
/* memcpy(find_tbuf, (void *)0x80, sizeof(*find_tbuf)); */
|
||||
@ -1140,12 +1151,14 @@ int generic_block_ioctl(unsigned drive, unsigned cx, unsigned char *par);
|
||||
int int2526readwrite(int DosDrive, void *diskReadPacket, unsigned intno)
|
||||
{
|
||||
union REGS regs;
|
||||
struct SREGS sregs;
|
||||
|
||||
regs.h.al = (BYTE) DosDrive;
|
||||
regs.x.bx = (short)diskReadPacket;
|
||||
regs.x.cx = 0xffff;
|
||||
sregs.ds = FP_SEG(diskReadPacket);
|
||||
|
||||
int86(intno, ®s, ®s);
|
||||
int86x(intno, ®s, ®s, &sregs);
|
||||
|
||||
return regs.x.cflag;
|
||||
}
|
||||
@ -1161,13 +1174,15 @@ int2526readwrite(DosDrive, diskReadPacket, 0x26)
|
||||
int fat32readwrite(int DosDrive, void *diskReadPacket, unsigned intno)
|
||||
{
|
||||
union REGS regs;
|
||||
struct SREGS sregs;
|
||||
|
||||
regs.x.ax = 0x7305;
|
||||
regs.h.dl = DosDrive;
|
||||
regs.x.bx = (short)diskReadPacket;
|
||||
regs.x.cx = 0xffff;
|
||||
regs.x.si = intno;
|
||||
intdos(®s, ®s);
|
||||
sregs.ds = FP_SEG(diskReadPacket);
|
||||
int86x(0x21, ®s, ®s, &sregs);
|
||||
|
||||
return regs.x.cflag;
|
||||
} /* fat32readwrite */
|
||||
@ -1292,10 +1307,15 @@ BOOL haveLBA(void); /* return TRUE if we have LBA BIOS, FALSE otherwise */
|
||||
BOOL haveLBA(void)
|
||||
{
|
||||
union REGS r;
|
||||
struct SREGS sr;
|
||||
r.x.ax = 0x4100;
|
||||
r.x.bx = 0x55AA;
|
||||
r.h.dl = 0x80;
|
||||
int86(0x13, &r, &r);
|
||||
sr.ds = 0x40;
|
||||
/* ds = 40h is to work around a Xi8088 ROM-BIOS bug,
|
||||
refer to https://github.com/FDOS/kernel/issues/156
|
||||
and https://www.bttr-software.de/forum/forum_entry.php?id=21275 */
|
||||
int86x(0x13, &r, &r, &sr);
|
||||
return r.x.bx == 0xAA55 && r.x.cx & 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user