Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[kernel] Split XMS/DMA buffer from track cache for BIOS and DF drivers #2094

Merged
merged 2 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 36 additions & 32 deletions elks/arch/i86/drivers/block/bioshd.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ static struct gendisk bioshd_gendisk = {

static void BFPROC set_cache_invalid(void)
{
if (cache_drive) debug_cache2("INV%d ", cache_drive - drive_info);
if (cache_drive) debug_cache("INV%d ", bios_drive_map[cache_drive - drive_info]);
cache_drive = NULL;
}

Expand Down Expand Up @@ -525,11 +525,11 @@ static void BFPROC get_chst(struct drive_infot *drivep, sector_t *start_sec,
#if FULL_TRACK
if (fulltrack) {
int save = *s;
int max_sectors = DMASEGSZ / drivep->sector_size;
int max_sectors = TRACKSEGSZ / drivep->sector_size;
if (*s - 1 < max_sectors) { /* adjust start sector backwards for full track read*/
*s = 1;
*t = max_sectors;
} else { /* likely 2880k: limit to size of DMASEG buffer */
} else { /* likely 2880k: limit to size of TRACKSEG buffer */
*s = max_sectors + 1;
*t = drivep->sectors - *s + 1;
}
Expand Down Expand Up @@ -559,30 +559,31 @@ static int BFPROC do_readwrite(struct drive_infot *drivep, sector_t start, char
if (cmd == READ) debug_bios("bioshd(%x): read lba %ld count %d\n",
drive, start, this_pass);

#pragma GCC diagnostic ignored "-Wshift-count-overflow"
usedmaseg = seg >> 16; /* will be nonzero only if XMS configured and XMS buffer */
if (!usedmaseg) {
/* check for 64k I/O overlap */
physaddr = (seg << 4) + (unsigned int)buf;
end = this_pass * drivep->sector_size - 1;
usedmaseg = (physaddr + end < physaddr);
debug_blk("bioshd: %p:%p = %p count %d wrap %d\n",
(unsigned int)seg, buf, physaddr, this_pass, usedmaseg);
}
if (usedmaseg) {
segment = DMASEG; /* if xms buffer use DMASEG*/
offset = 0;
if (cmd == WRITE) /* copy xms buffer down before write*/
xms_fmemcpyw(0, DMASEG, buf, seg, this_pass*(drivep->sector_size >> 1));
//set_cache_invalid(); /* don't invalidate cache - not shared */
} else {
segment = (seg_t)seg;
offset = (unsigned) buf;
}
errs = MAX_ERRS; /* BIOS disk reads should be retried at least five times */
do {
#pragma GCC diagnostic ignored "-Wshift-count-overflow"
usedmaseg = seg >> 16; /* will be nonzero only if XMS configured and XMS buffer */
if (!usedmaseg) {
/* check for 64k I/O overlap */
physaddr = (seg << 4) + (unsigned int)buf;
end = this_pass * drivep->sector_size - 1;
usedmaseg = (physaddr + end < physaddr);
debug_blk("bioshd: %p:%p = %p count %d wrap %d\n",
(unsigned int)seg, buf, physaddr, this_pass, usedmaseg);
}
if (usedmaseg) {
segment = DMASEG; /* if xms buffer use DMASEG*/
offset = 0;
if (cmd == WRITE) /* copy xms buffer down before write*/
xms_fmemcpyw(0, DMASEG, buf, seg, this_pass*(drivep->sector_size >> 1));
set_cache_invalid();
} else {
segment = (seg_t)seg;
offset = (unsigned) buf;
}
debug_cache("%s%d CHS %d/%d/%d count %d\n",
cmd==WRITE? "WR": "RD", drive, cylinder, head, sector, this_pass);
debug_cache("%s%s%d CHS %d/%d/%d count %d\n",
cmd==WRITE? "WR": "RD", usedmaseg? "X": "", drive, cylinder, head, sector,
this_pass);
debug_bios("bioshd(%x): cmd %d CHS %d/%d/%d count %d\n",
drive, cmd, cylinder, head, sector, this_pass);

Expand All @@ -597,12 +598,15 @@ static int BFPROC do_readwrite(struct drive_infot *drivep, sector_t start, char
} while (error && --errs); /* On error, retry up to MAX_ERRS times */
last_drive = drivep;

if (cmd == WRITE && drivep == cache_drive)
set_cache_invalid(); /* cache not updated on write so invalidate */

if (error) return 0; /* error message in blk.h */

if (usedmaseg) {
if (cmd == READ) /* copy DMASEG up to xms*/
xms_fmemcpyw(buf, seg, 0, DMASEG, this_pass*(drivep->sector_size >> 1));
set_cache_invalid();
//set_cache_invalid(); /* don't invalidate cache - not shared */
}
return this_pass;
}
Expand All @@ -611,7 +615,7 @@ static int BFPROC do_readwrite(struct drive_infot *drivep, sector_t start, char
static sector_t cache_startsector;
static sector_t cache_endsector;

/* read from start sector to end of track into DMASEG track buffer, no retries*/
/* read from start sector to end of track into TRACKSEG track buffer, no retries*/
static void BFPROC do_readtrack(struct drive_infot *drivep, sector_t start)
{
unsigned int cylinder, head, sector, num_sectors;
Expand All @@ -621,8 +625,8 @@ static void BFPROC do_readtrack(struct drive_infot *drivep, sector_t start)
drive = bios_drive_map[drive];
get_chst(drivep, &start, &cylinder, &head, &sector, &num_sectors, 1);

if (num_sectors > (DMASEGSZ / drivep->sector_size))
num_sectors = DMASEGSZ / drivep->sector_size;
if (num_sectors > (TRACKSEGSZ / drivep->sector_size))
num_sectors = TRACKSEGSZ / drivep->sector_size;

do {
debug_cache("\nTR%d %lu(CHS %u,%u,%u-%u) ", drive, start>>1, cylinder, head,
Expand All @@ -632,7 +636,7 @@ static void BFPROC do_readtrack(struct drive_infot *drivep, sector_t start)

bios_set_ddpt(drivep->sectors);
error = bios_disk_rw(BIOSHD_READ, num_sectors, drive,
cylinder, head, sector, DMASEG, 0);
cylinder, head, sector, TRACKSEG, 0);
if (error) {
printk("bioshd(%x): track read retry #%d CHS %d/%d/%d count %d\n",
drive, errs + 1, cylinder, head, sector, num_sectors);
Expand Down Expand Up @@ -665,7 +669,7 @@ static int BFPROC cache_valid(struct drive_infot *drivep, sector_t start, char *
offset = (int)(start - cache_startsector) * drivep->sector_size;
debug_bios("bioshd(%x): cache hit lba %ld\n",
bios_drive_map[drivep-drive_info], start);
xms_fmemcpyw(buf, seg, (void *)offset, DMASEG, drivep->sector_size >> 1);
xms_fmemcpyw(buf, seg, (void *)offset, TRACKSEG, drivep->sector_size >> 1);
return 1;
}

Expand All @@ -686,8 +690,8 @@ static int BFPROC do_cache_read(struct drive_infot *drivep, sector_t start, char
do_readtrack(drivep, start); /* read whole track*/
if (cache_valid(drivep, start, buf, seg)) /* try cache again*/
return 1;
//set_cache_invalid(); /* old code invalidated cache on failure */
}
set_cache_invalid();
return 0;
}
#endif
Expand Down
6 changes: 3 additions & 3 deletions elks/arch/i86/drivers/block/directfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,10 @@ char USE_IMPLIED_SEEK = 0; /* =1 for QEMU with 360k/AT stretch floppies (not rea
#define TIMEOUT_CMD_COMPL (6 * HZ) /* 6 secs wait for FDC command complete */

/* locations for cache and bounce buffers */
#define CACHE_SEG DMASEG /* track cache at DMASEG:0 (shared with BIOS driver) */
#define CACHE_OFF 0
#define BOUNCE_SEG DMASEG /* share bounce buffer with track cache at DMASEG:0 */
#define BOUNCE_SEG TRACKSEG /* share bounce buffer with track cache at TRACKSEG:0 */
#define BOUNCE_OFF 0
#define CACHE_SEG TRACKSEG /* track cache at TRACKSEG:0 (same as BIOS FD driver) */
#define CACHE_OFF 0

#define FLOPPY_DMA 2 /* hardwired on old PCs */

Expand Down
42 changes: 29 additions & 13 deletions elks/include/linuxmt/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,27 +103,43 @@
#define DEF_SETUPSEG DEF_INITSEG + 0x20
#define DEF_SYSMAX 0x2F00 /* maximum system size (=.text+.fartext+.data) */

/* Segment DMASEG up to DMASEGEND is used as a bounce buffer of at least 1K (=BLOCKSIZE)
* below the first 64K boundary (=0x1000:0) for use with the old 8237 DMA controller.
* If floppy track caching is enabled, this area is also used for the track buffer
* for direct DMA access using multisector I/O.
* Following DMASEGEND is the kernel code and data at REL_SYSSEG.
/* Segment DMASEG up to DMASEGEND is used for the XMS/DMA bounce buffer and track cache.
* Following DMASEGEND is the kernel code at REL_SYSSEG (or kernel data for ROM configs).
*
* A "bounce buffer" is configured below the first 64K boundary for use with
* old 8237 DMA controller which wraps addresses wider than 16-bits on PC/XT systems.
* If floppy track caching is enabled, the track buffer is also configured in
* low memory for direct DMA access usig multisector I/O.
* The DF driver uses the first sector of its track cache for the XMS/DMA buffer.
* In contrast, the BIOS FD/HD driver is configured to use an XMS/DMA buffer
* outside its track cache; thus the complicated defines below.
*/

#if defined(CONFIG_BLK_DEV_BFD) || defined(CONFIG_BLK_DEV_BHD) /* BIOS driver */
#define DMASEGSZ 0x0400 /* BLOCK_SIZE (1024) for external XMS/DMA buffer */
#else
#define DMASEGSZ 0 /* no external XMS/DMA buffer */
#endif

#if defined(CONFIG_BLK_DEV_BFD) || defined(CONFIG_BLK_DEV_BHD) || defined(CONFIG_BLK_FD)
#ifdef CONFIG_TRACK_CACHE /* floppy track buffer in low mem */
#define DMASEGSZ 0x2400 /* SECTOR_SIZE * 18 (9216) */
# define TRACKSEGSZ 0x2400 /* SECTOR_SIZE * 18 (9216) */
#else
#define DMASEGSZ 0x0400 /* BLOCK_SIZE (1024) */
# ifdef CONFIG_BLK_FD
# define TRACKSEGSZ 0x0400 /* DF driver requires DMASEG internal to TRACKSEG */
# else
# define TRACKSEGSZ 0 /* no TRACKSEG buffer */
# endif
#endif
#define TRACKSEG (DMASEG+(DMASEGSZ>>4))
#define DMASEGEND (DMASEG+(DMASEGSZ>>4)+(TRACKSEGSZ>>4))
#else
#define DMASEGEND DMASEG /* no DMASEG buffer */
#endif
#define DMASEGEND (DMASEG+(DMASEGSZ>>4))

#ifdef CONFIG_ROMCODE
#if defined(CONFIG_BLK_DEV_BFD) || defined(CONFIG_BLK_DEV_BHD) /* BIOS disk driver*/
#define DMASEG 0x80 /* 0x400 bytes floppy sector buffer */
#define DMASEG 0x80 /* start of floppy sector buffer */
#define KERNEL_DATA DMASEGEND /* kernel data segment */
#else
#define KERNEL_DATA 0x080 /* kernel data segment */
#endif
#define SETUP_DATA CONFIG_ROM_SETUP_DATA
#endif

Expand Down
12 changes: 5 additions & 7 deletions emu86.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,18 @@
# Kernel image @ segment 0xE000 (as 64K BIOS extension)
# Root filesystem @ segment 0x8000 (assumes 512K RAM & 512K ROM)

# 8088 version using emu-rom-full.config from './buildimages.sh fast'
# 8088 ROM version using emu-rom-full.config from './buildimages.sh fast'
exec emu86 -w 0xe0000 -f image/rom-8088.bin -w 0x80000 -f image/romfs-8088.bin ${1+"$@"}

# just built rom version using 'make'
exec emu86 -w 0xe0000 -f elks/arch/i86/boot/Image -w 0x80000 -f image/romfs.bin ${1+"$@"}
# just built ROM version using 'make'
#exec emu86 -w 0xe0000 -f elks/arch/i86/boot/Image -w 0x80000 -f image/romfs.bin ${1+"$@"}

# For ELKS Full ROM Configuration:
# ELKS must be configured minimally with 'cp emu86-rom-full.config .config'
# This adds MINIX/FAT filesytems with BIOS driver

exec emu86 -w 0xe0000 -f elks/arch/i86/boot/Image -w 0x80000 -f image/romfs.bin -I image/fd1440.bin ${1+"$@"}
#exec emu86 -w 0xe0000 -f image/rom-8088.bin -w 0x80000 -f image/romfs-8088.bin -I image/fd1440.img ${1+"$@"}

# For ELKS disk image Configuration:
# ELKS must be configured with 'cp emu86-disk.config .config'
# This uses headless console, HLT on idle, no CONFIG_IDE_PROBE

exec emu86 -I image/fd1440.bin ${1+"$@"}
#exec emu86 -I image/fd1440.img ${1+"$@"}
Loading