SYS and printer fixes

git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@307 6ac86273-5f31-0410-b378-82cca8765d1b
This commit is contained in:
Bart Oldeman 2001-09-24 02:21:14 +00:00
parent a957122ff6
commit c8f7d66461
7 changed files with 718 additions and 65 deletions

362
boot/boot32.asm Normal file
View File

@ -0,0 +1,362 @@
; +--------+
; | |
; | |
; |--------| 4000:0000
; | |
; | FAT |
; | |
; |--------| 2000:0000
; |BOOT SEC|
; |RELOCATE|
; |--------| 1FE0:0000
; | |
; | |
; | |
; | |
; |--------|
; |BOOT SEC|
; |ORIGIN | 07C0:0000
; |--------|
; | |
; | |
; | |
; |--------|
; |KERNEL |
; |LOADED |
; |--------| 0060:0000
; | |
; +--------+
;%define MULTI_SEC_READ 1
segment .text
%define BASE 0x7c00
org BASE
Entry: jmp short real_start
nop
; bp is initialized to 7c00h
%define bsOemName bp+0x03 ; OEM label
%define bsBytesPerSec bp+0x0b ; bytes/sector
%define bsSecPerClust bp+0x0d ; sectors/allocation unit
%define bsResSectors bp+0x0e ; # reserved sectors
%define bsFATs bp+0x10 ; # of fats
%define bsRootDirEnts bp+0x11 ; # of root dir entries
%define bsSectors bp+0x13 ; # sectors total in image
%define bsMedia bp+0x15 ; media descrip: fd=2side9sec, etc...
%define sectPerFat bp+0x16 ; # sectors in a fat
%define sectPerTrack bp+0x18 ; # sectors/track
%define nHeads bp+0x1a ; # heads
%define nHidden bp+0x1c ; # hidden sectors
%define nSectorHuge bp+0x20 ; # sectors if > 65536
%define xsectPerFat bp+0x24 ; Sectors/Fat
%define xrootClst bp+0x2c ; Starting cluster of root directory
%define drive bp+0x40 ; Drive number
%define LOADSEG 0x0060
%define FATSEG 0x2000
%define fat_sector bp+0x48 ; last accessed sector of the FAT
dd 0
times 0x5a-$+$$ db 0
%define fat_start bp+0x5a ; first FAT sector
dd 0
%define data_start bp+0x5e ; first data sector
dd 0
%define fat_secmask bp+0x62 ; number of clusters in a FAT sector - 1
dw 0
%define fat_secshift bp+0x64 ; fat_secmask+1 = 2^fat_secshift
dw 0
;-----------------------------------------------------------------------
; ENTRY
;-----------------------------------------------------------------------
real_start: cld
sub ax, ax
mov ds, ax
mov bp, 0x7c00
mov ss, ax ; initialize stack
lea sp, [bp-0x20]
int 0x13 ; reset drive
mov ax, 0x1FE0
mov es, ax
mov si, bp
mov di, bp
mov cx, 0x0100
rep movsw ; move boot code to the 0x1FE0:0x0000
push es
mov bx, cont
push bx
retf
cont: mov ds, ax
mov ss, ax
mov [drive], dl ; BIOS passes drive number in DL
call print
db "Loading FreeDOS...",13,10,0
; FINDFILE: Searches for the file in the root directory.
;
; Returns:
; DX:AX = first cluster of file
mov word [fat_sector], cx ; CX is 0 after movsw
mov word [fat_sector + 2], cx
mov ax, word [xrootClst]
mov dx, word [xrootClst + 2]
ff_next_cluster:
push dx ; save cluster
push ax
call convert_cluster
jc boot_error ; EOC encountered
ff_next_sector:
push bx ; save sector count
mov bx, LOADSEG
mov es, bx
sub bx, bx
call readDisk
push dx ; save sector
push ax
mov ax, [bsBytesPerSec]
; Search for KERNEL.SYS file name, and find start cluster.
ff_next_entry: mov cx, 11
mov si, filename
mov di, ax
sub di, 0x20
repe cmpsb
jz ff_done
sub ax, 0x20
jnz ff_next_entry
pop ax ; restore sector
pop dx
pop bx ; restore sector count
dec bx
jnz ff_next_sector
ff_find_next_cluster:
pop ax ; restore current cluster
pop dx
call next_cluster
jmp ff_next_cluster
ff_done:
mov ax, [es:di+0x1A-11] ; get cluster number
mov dx, [es:di+0x14-11]
c4:
sub bx, bx ; ES points to LOADSEG
c5: push dx
push ax
push bx
call convert_cluster
jc boot_success
mov di, bx
pop bx
c6:
call readDisk
dec di
jnz c6
pop ax
pop dx
call next_cluster
jmp c5
boot_error: call print
db 13,10,"BOOT error!",13,10,0
xor ah,ah
int 0x16 ; wait for a key
int 0x19 ; reboot the machine
; input:
; DX:AX - cluster
; output:
; DX:AX - next cluster
; CX = 0
; modify:
; DI
next_cluster:
push es
mov di, ax
and di, [fat_secmask]
mov cx, [fat_secshift]
cn_loop:
shr dx,1
rcr ax,1
dec cx
jnz cn_loop ; DX:AX fat sector where our
; cluster resides
; DI - cluster index in this
; sector
shl di,1 ; DI - offset in the sector
shl di,1
add ax, [fat_start]
adc dx, [fat_start+2] ; DX:AX absolute fat sector
push bx
mov bx, FATSEG
mov es, bx
sub bx, bx
cmp ax, [fat_sector]
jne cn1 ; if the last fat sector we
; read was this, than skip
cmp dx,[fat_sector+2]
je cn_exit
cn1:
mov [fat_sector],ax ; save the fat sector number,
mov [fat_sector+2],dx ; we are going to read
call readDisk
cn_exit:
pop bx
mov ax, [es:di] ; DX:AX - next cluster
mov dx, [es:di + 2] ;
pop es
ret
boot_success:
mov bl, [drive]
jmp word LOADSEG:0
; Convert cluster to the absolute sector
;input:
; DX:AX - target cluster
;output:
; DX:AX - absoulute sector
; BX - [bsSectPerClust]
;modify:
; CX
convert_cluster:
cmp dx,0x0fff
jne c3
cmp ax,0xfff8
jb c3 ; if cluster is EOC (carry is set), do ret
stc
ret
c3:
mov cx, dx ; sector = (cluster - 2)*clussize +
; + data_start
sub ax, 2
sbb cx, byte 0 ; CX:AX == cluster - 2
mov bl, [bsSecPerClust]
sub bh, bh
xchg cx, ax ; AX:CX == cluster - 2
mul bx ; first handle high word
; DX must be 0 here
xchg ax, cx ; then low word
mul bx
add dx, cx ; DX:AX target sector
add ax, [data_start]
adc dx, [data_start + 2]
ret
; prints text after call to this function.
print: pop si ; this is the first character
xor bx, bx ; video page 0
mov ah, 0x0E ; else print it
print1: lodsb ; get token
cmp al, bl ; end of string? (al == bl == 0)
je print2 ; if so, exit
int 0x10 ; via TTY mode
jmp short print1 ; until done
print2: push si ; stack up return address
ret ; and jump to it
;input:
; DX:AX - 32-bit DOS sector number
; ES:BX - destination buffer
;output:
; ES:BX points one byte after the last byte read.
; DX:AX - next sector
;modify:
; ES if DI * bsBytesPerSec >= 65536, CX
readDisk:
read_next: push dx
push ax
;
; translate sector number to BIOS parameters
;
;
; abs = sector offset in track
; + head * sectPerTrack offset in cylinder
; + track * sectPerTrack * nHeads offset in platter
;
; t1 = abs / sectPerTrack (ax has t1)
; sector = abs mod sectPerTrack (cx has sector)
;
div word [sectPerTrack]
mov cx, dx
;
; t1 = head + track * nHeads
;
; track = t1 / nHeads (ax has track)
; head = t1 mod nHeads (dl has head)
;
xor dx, dx
div word [nHeads]
; the following manipulations are necessary in order to
; properly place parameters into registers.
; ch = cylinder number low 8 bits
; cl = 7-6: cylinder high two bits
; 5-0: sector
mov dh, dl ; save head into dh for bios
ror ah, 1 ; move track high bits into
ror ah, 1 ; bits 7-6 (assumes top = 0)
xchg al, ah ; swap for later
mov dl, byte [sectPerTrack]
sub dl, cl
inc cl ; sector offset from 1
or cx, ax ; merge cylinder into sector
mov ax, 0x0201
mov dl, [drive]
int 0x13
pop ax
pop dx
jnc read_ok ; jump if no error
xor ah, ah ; else, reset floppy
int 0x13
jmp read_next
read_ok:
add bx, word [bsBytesPerSec]
jnc no_incr_es ; if overflow...
mov cx, es
add ch, 0x10 ; ...add 1000h to ES
mov es, cx
no_incr_es:
add ax,byte 1
adc dx,byte 0
ret
filename db "KERNEL SYS"
times 0x01fe-$+$$ db 0
sign dw 0xAA55

24
docs/lfnapi.txt Normal file
View File

@ -0,0 +1,24 @@
FreeDOS LFN aid API.
struct lfn_inode
{
UNICODE name[255];
struct dirent l_dir; /* this file's dir entry image */
ULONG l_diroff; /* offset of the dir entry */
CLUSTER l_dirstart; /* the starting cluster of dir */
/* when dir is not root */
};
typedef struct lfn_inode FAR * lfn_inode_ptr;
COUNT lfn_allocate_inode();
COUNT lfn_free_inode(COUNT handle);
COUNT lfn_create_entries(COUNT handle, lfn_inode_ptr lip);
COUNT lfn_remove_entries(COUNT handle, lfn_inode_ptr lip);
COUNT lfn_dir_read(COUNT handle, lfn_inode_ptr lip);
COUNT lfn_dir_write(COUNT handle, lfn_inode_ptr lip);

84
hdr/xstructs.h Normal file
View File

@ -0,0 +1,84 @@
/****************************************************************/
/* */
/* xstructs.h */
/* */
/* Extended DOS 7.0+ structures */
/* */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *XStructs_hRcsId = "$Id$";
#endif
#endif
struct xdpbdata
{
UWORD xdd_dpbsize;
struct dpb xdd_dpb;
};
struct xfreespace
{
UWORD xfs_datasize; /* size of this structure */
union {
UWORD requested; /* requested structure version */
UWORD actual; /* actual structure version */
} xfs_version;
ULONG xfs_clussize; /* number of sectors per cluster */
ULONG xfs_secsize; /* number of bytes per sector */
ULONG xfs_freeclusters; /* number of available clusters */
ULONG xfs_totalclusters; /* total number of clusters on the drive */
ULONG xfs_freesectors; /* number of physical sectors available */
ULONG xfs_totalsectors; /* total number of physical sectors */
ULONG xfs_freeunits; /* number of available allocation units */
ULONG xfs_totalunits; /* total allocation units */
UBYTE xfs_reserved[8];
};
struct xdpbforformat
{
UWORD xdff_datasize; /* size of this structure */
union {
UWORD requested; /* requested structure version */
UWORD actual; /* actual structure version */
} xdff_version;
UDWORD xdff_function; /* function number:
00h invalidate DPB counts
01h rebuild DPB from BPB
02h force media change
03h get/set active FAT number and mirroring
04h get/set root directory cluster number
*/
union {
struct {
DWORD nfreeclst; /* # free clusters
(-1 - unknown, 0 - don't change) */
DWORD cluster; /* cluster # of first free
(-1 - unknown, 0 - don't change) */
UDWORD reserved[2];
} setdpbcounts;
struct {
UDWORD unknown;
bpb FAR *bpbp;
UDWORD reserved[2];
} rebuilddpb;
struct {
DWORD newmirroring; /* new active FAT/mirroring state, or -1 to get
bits 3-0: the 0-based FAT number of the active FAT
bits 6-4: reserved (0)
bit 7: do not mirror active FAT to inactive FATs
*/
DWORD oldmirroring; /* previous active FAT/mirroring state (as above) */
UDWORD reserved[2];
} setmirroring;
struct {
DWORD newrootclst; /* set new root directory cluster, -1 - get current */
DWORD oldrootclst; /* get previous root directory cluster */
UDWORD reserved[2];
} setroot;
} xdff_f;
};

View File

@ -37,6 +37,9 @@ static BYTE *dosfnsRcsId = "$Id$";
* /// Added SHARE support. 2000/09/04 Ron Cemer
*
* $Log$
* Revision 1.27 2001/09/24 02:21:14 bartoldeman
* SYS and printer fixes
*
* Revision 1.26 2001/09/23 20:39:44 bartoldeman
* FAT32 support, misc fixes, INT2F/AH=12 support, drive B: handling
*
@ -551,16 +554,15 @@ UCOUNT DosWrite(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err)
}
else
{
REG WORD /*c,*/
cnt = n,
xfer = 0;
REG WORD xfer;
while(cnt-- != 0 && *bp != CTL_Z){
for(xfer = 0; xfer < n && *bp != CTL_Z; bp++, xfer++)
{
if (s->sft_flags & SFT_FCONOUT)
{
cso(*bp);
}
else
else FOREVER
{
rq.r_length = sizeof(request);
rq.r_command = C_OUTPUT;
@ -568,11 +570,24 @@ UCOUNT DosWrite(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err)
rq.r_trans = bp;
rq.r_status = 0;
execrh((request FAR *) & rq, s->sft_dev);
if (rq.r_status & S_ERROR)
char_error(&rq, s->sft_dev);
if (!(rq.r_status & S_ERROR))
break;
charloop:
switch(char_error(&rq, s->sft_dev))
{
case ABORT:
case FAIL:
*err = DE_INVLDACC;
return xfer;
case CONTINUE:
break;
case RETRY:
continue;
default:
goto charloop;
}
break;
}
++bp;
++xfer;
if (control_break())
{
handle_break();

31
kernel/init-dat.h Normal file
View File

@ -0,0 +1,31 @@
/* Included by initialisation functions */
#if _MSC_VER != 0
extern __segment DosDataSeg;/* serves for all references to the DOS DATA segment
necessary for MSC+our funny linking model
*/
extern __segment DosTextSeg;
#define DOSFAR __based(DosDataSeg)
#define DOSTEXTFAR __based(DosTextSeg)
#elif defined(__TURBOC__)
#define DOSFAR FAR
#define DOSTEXTFAR FAR
#elif defined(__WATCOMC__)
#define DOSFAR FAR
#define DOSTEXTFAR FAR
#else
#pragma error("unknown compiler - please adjust")
this should simply not compile !!
#endif
extern BYTE DOSFAR version_flags; /* minor version number */

147
kernel/lfnapi.c Normal file
View File

@ -0,0 +1,147 @@
/****************************************************************/
/* */
/* lfnapi.c */
/* */
/* Directory access functions for LFN aid API */
/* Module is under construction! */
/****************************************************************/
#include "portab.h"
#include "globals.h"
#ifdef VERSION_STRINGS
static BYTE *lfnaidRcsId = "$Id$";
#endif
#if 0
#define E_INVLDHNDL -1
#define E_NOFREEHNDL -2
#define E_IOERROR -3
#define E_INVLDDRV -4
COUNT lfn_allocate_inode()
{
f_node_ptr fnp = get_f_node();
struct cds FAR *cdsp;
if (fnp == 0) return E_NOFREEHNDL;
cdsp = &CDSp->cds_table[default_drive];
if (cdsp->cdsDpb == 0)
{
release_f_node(fnp);
return E_INVLDDRV;
}
fnp->f_dpb = cdsp->cdsDpb;
if (media_check(fnp->f_dpb) < 0)
{
release_f_node(fnp);
return E_INVLDDRV;
}
fnp->f_dsize = DIRENT_SIZE * fnp->f_dpb->dpb_dirents;
return xlt_fnp(fnp);
}
COUNT lfn_free_inode(COUNT handle)
{
f_node_ptr fnp = xlt_fd(handle);
if (fnp == 0 || fnp->f_count <= 0) return E_INVLHNDL;
release_f_node(fnp);
}
COUNT lfn_to_unicode_chunk(UNICODE FAR **nptr, UNICODE FAR **uptr,
UCOUNT *index, COUNT count)
{
COUNT j;
for (j = 0; j < count; j++, *uptr++, *index++, *nptr++)
{
**nptr = **uptr;
if (**uptr == 0) return 0;
}
return 1;
}
COUNT lfn_to_unicode(UNICODE FAR *name, UBYTE FAR *lfn_entry, UCOUNT *index)
{
COUNT j;
UNICODE FAR *uptr;
UNICODE FAR *nptr = name;
uptr = (UNICODE FAR *)&lfn_entry[1];
if (!lfn_to_unicode_chunk(&nptr, &uptr, index, 5)) return 0;
uptr = (UNICODE FAR *)&lfn_entry[0xe];
if (!lfn_to_unicode_chunk(&nptr, &uptr, index, 6)) return 0;
uptr = (UNICODE FAR *)&lfn_entry[0x1c];
if (!lfn_to_unicode_chunk(&nptr, &uptr, index, 2)) return 0;
return 1;
}
COUNT lfn_dir_read(COUNT handle, lfn_inode_ptr lip)
{
COUNT index = 0; /* index of the first non-filled char in the long file
name string */
ULONG original_diroff;
f_node_ptr fnp = xlt_fd(handle);
if (fnp == 0 || fnp->f_count <= 0) return E_INVLHNDL;
if (lfnp->l_dirstart == 0)
{
}
original_diroff = fnp->f_diroff;
lip->name[0] = 0;
while (TRUE)
{
if (dir_read(fnp) != DIRENT_SIZE) return E_IOERROR;
if (fnp->f_dir.dir_name[0] != DELETED && fnp->f_dir.dir_name[0] != 0
&& fnp->f_dir.dir_attrib != D_LFN)
{
fmemcpy(lip->l_dir, fnp->f_dir, sizeof(struct dirent));
lip->l_diroff = fnp->f_diroff;
lip->l_dirstart = fnp->f_dirstart;
break;
}
}
fnp->f_diroff = original_diroff - DIRENT_SIZE;
while (TRUE)
{
if (fnp->f_diroff == 0) break;
fnp->f_diroff -= 2*DIRENT_SIZE;
if (dir_read(fnp) != DIRENT_SIZE) return E_IOERROR;
if (fnp->f_dir.dir_name[0] == '\0'
|| fnp->f_dir.dir_name[0] == DELETED) break;
if (!lfn_to_unicode(lip->name,
(UBYTE FAR *)fnp->f_dir, index)) break;
}
if (lip->name[0] == 0)
{
ConvertName83ToNameSZ(lip->name, lip->l_dir.dir_name);
}
return SUCCESS;
}
/* Calculate checksum for the 8.3 name */
UBYTE lfn_checksum(char *name)
{
UBYTE sum;
COUNT i;
for (sum = 0, i = 11; --i >= 0; sum += *name++)
sum = (sum << 7) | (sum >> 1);
return sum;
}
#endif

View File

@ -28,6 +28,9 @@
; $Header$
;
; $Log$
; Revision 1.5 2001/09/24 02:21:14 bartoldeman
; SYS and printer fixes
;
; Revision 1.4 2001/09/23 20:39:44 bartoldeman
; FAT32 support, misc fixes, INT2F/AH=12 support, drive B: handling
;
@ -106,19 +109,29 @@ uPrtQuantum dw 50h
PrtWrite:
jcxz PrtWr3 ; Exit if nothing to write
PrtWr1:
mov bx,2 ; number of retries
PrtWr2:
call PrintSingleCharacter
PrtCharLoop: ; next character loop
mov bx, 2 ; number of retries
PrtRetryTwice:
mov ah, PRT_GETSTATUS ; get status, ah=2
call PrtIOCall ;
jnz PrtWr4
jnz PrtWr4 ; Exit if done
loop PrtWr1 ; otherwise loop
mov al,[es:di]
mov ah, PRT_WRITECHAR ; print character, ah=0
call PrtIOCall ; (0800)
jnz PrtWr4 ; NZ = error, retry
inc di
loop PrtCharLoop ; next character
PrtWr3:
jmp _IOExit
PrtWr4:
PrtWr4: ; repeat
dec bx
jnz PrtWr2
jnz PrtRetryTwice
PrtWr5:
jmp _IOErrCnt
@ -141,18 +154,27 @@ GetPrtStat:
PrtIOCall:
call GetUnitNum
int 17h ; print char al, get status ah
test ah, PRT_TIMEOUT|PRT_IOERROR
jnz PrtIOCal2
mov al, E_PAPER
test ah, PRT_OUTOFPAPER
jnz PrtIOCal1
inc al ; al<-E_WRITE
PrtIOCal1:
retn
PrtIOCal2:
int 17h ; print char al, get status ah
mov al, ah ; if (stat & 0x30) == 0x30 return 10;
and al, PRT_SELECTED|PRT_OUTOFPAPER
cmp al, PRT_SELECTED|PRT_OUTOFPAPER
mov al, E_WRITE
je ret_error_code
test ah, PRT_OUTOFPAPER|PRT_IOERROR|PRT_TIMEOUT ; 29h
mov al, E_NOTRDY
test ah, PRT_TIMEOUT
jz ret_error_code
test ah, PRT_OUTOFPAPER ; 20h
mov al, E_WRITE
jz ret_error_code ; not out of paper -> E_WRITE
ret_error_code_9:
mov al, E_PAPER
ret_error_code:
cmp al, E_NOTRDY ; 2 = no error
retn
@ -222,8 +244,11 @@ PrtGnIoctl3:
;
; original implementation didn't work at all.
; this one's not much better either,
; some comments to last changes (TE, 23/09/01)
;
; original implementation didn't print at all - on my machine,LPT2
;
; maybe this one's not much better either,
; but should print a little bit
;
; the status bits = AH
@ -242,42 +267,7 @@ PrtGnIoctl3:
; 10 - printer with power, but not initialized
; 90 - this one is fine
;
; you must not simply print without asking for status
; as the BIOS has a LARGE timeout before aborting
;
PrintSingleCharacter:
mov ah, PRT_GETSTATUS ; get status, ah=2
call GetUnitNum
int 17h ; print char al, get status ah
test ah, PRT_OUTOFPAPER|PRT_IOERROR
jnz decode_error
test ah, PRT_NOTBUSY
jz decode_error
mov al,[es:di]
mov ah,PRT_WRITECHAR ; print character, ah=0
call GetUnitNum
int 17h ; print char al, get status ah
test ah, PRT_OUTOFPAPER|PRT_IOERROR|PRT_TIMEOUT
jnz decode_error
inc di
xor al,al ; set zero flag + clear al
ret
decode_error:
mov al, E_PAPER
test ah, PRT_OUTOFPAPER ;out_of_paper, 20h
jnz out_of_paper
mov al, E_WRITE
out_of_paper:
or al,al ; reset zero flag
ret