From 8fb68f4d2b6f57348bbf79e3990fb8439c5c6ff3 Mon Sep 17 00:00:00 2001 From: Greg Haerr Date: Wed, 6 Nov 2024 11:58:28 -0800 Subject: [PATCH 1/4] [direct floppy] Revise cache numbering scheme for more flexibility --- elks/arch/i86/drivers/block/directfd.c | 60 +++++++++++++------------- elks/init/main.c | 2 +- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/elks/arch/i86/drivers/block/directfd.c b/elks/arch/i86/drivers/block/directfd.c index 4fb22cb0b..7b9e3857f 100644 --- a/elks/arch/i86/drivers/block/directfd.c +++ b/elks/arch/i86/drivers/block/directfd.c @@ -285,13 +285,14 @@ static int probing; /* set when determining media format */ static bool use_cache; /* expand read request to fill cache when set */ static int use_bounce; /* XMS I/O or 64k address wrap when set */ static unsigned char cache_drive = 255; -static unsigned char cache_startsector; /* cache start sector */ -static int cache_track; +static unsigned int cache_start; /* logical sector number */ +static unsigned int cache_numsectors; /* size of cache in sectors */ static int cur_spec1 = -1; static int cur_rate = -1; static struct floppy_struct *floppy; static unsigned char current_drive = 255; static unsigned char sector; /* zero relative requested I/O sector */ +static unsigned int numsectors; /* # sectors in I/O */ static unsigned char startsector; /* zero relative actual I/O start sector */ static unsigned char head; static unsigned char track; @@ -475,13 +476,18 @@ static void DFPROC setup_DMA(void) DEBUG("setupDMA "); dma_addr = LINADDR(CACHE_SEG, CACHE_OFF); - count = req->rq_nr_sectors << 9; + count = numsectors << 9; physaddr = (req->rq_seg << 4) + (unsigned int)req->rq_buffer; #pragma GCC diagnostic ignored "-Wshift-count-overflow" use_bounce = (req->rq_seg >> 16) || (physaddr + count) < physaddr; if (!use_cache) { /* use_cache overrides use_bounce */ if (use_bounce) { dma_addr = LINADDR(BOUNCE_SEG, BOUNCE_OFF); + if (use_bounce && command == FD_WRITE) { + printk("XWRITE "); + xms_fmemcpyw(BOUNCE_OFF, BOUNCE_SEG, req->rq_buffer, req->rq_seg, + BLOCK_SIZE/2); + } #if (BOUNCE_SEG == CACHE_SEG) && (BOUNCE_OFF == CACHE_OFF) invalidate_cache(); #endif @@ -489,12 +495,6 @@ static void DFPROC setup_DMA(void) dma_addr = LINADDR(req->rq_seg, req->rq_buffer); } - if (use_cache) { - /* read full or partial one side + split block */ - count = (floppy->sect + (floppy->sect & 1 && !head) - startsector) << 9; - } else if (use_bounce && command == FD_WRITE) { - xms_fmemcpyw(BOUNCE_OFF, BOUNCE_SEG, req->rq_buffer, req->rq_seg, BLOCK_SIZE/2); - } DEBUG("%d/%lx;", count, dma_addr); clr_irq(); @@ -657,6 +657,7 @@ static void rw_interrupt(void) { struct request *req = CURRENT; int nr, bad; + unsigned int start; char *cache_offset; nr = result(); @@ -728,9 +729,10 @@ static void rw_interrupt(void) } if (use_cache) { cache_drive = current_drive; /* cache now valid */ - cache_track = (seek_track << 1) + head; - cache_startsector = startsector; - cache_offset = (char *)(((sector - cache_startsector) << 9) + CACHE_OFF); + start = (unsigned int)req->rq_sector; + cache_start = FULL_TRACK? start - sector: start; + cache_numsectors = numsectors; + cache_offset = (char *)(((start - cache_start) << 9) + CACHE_OFF); DEBUG("rd %04x:%04x->%08lx:%04x;", CACHE_SEG, cache_offset, (unsigned long)req->rq_seg, req->rq_buffer); xms_fmemcpyw(req->rq_buffer, req->rq_seg, cache_offset, CACHE_SEG, BLOCK_SIZE/2); @@ -759,28 +761,22 @@ static void rw_interrupt(void) static void DFPROC setup_rw_floppy(void) { DEBUG("setup_rw-"); - startsector = (use_cache && FULL_TRACK)? 0: sector; -#if IODELAY || DEBUG_CACHE - int num_sectors = use_cache - ? floppy->sect + (floppy->sect & 1 && !head) - startsector - : CURRENT->rq_nr_sectors; #if IODELAY static unsigned lasttrack; unsigned ms = abs(track - lasttrack) * 4 / 10; lasttrack = track; if (current_drive == 0) - ms += 10 + num_sectors; /* 1440k @300rpm = 100ms + ~10ms/sector + 4ms/tr */ + ms += 10 + numsectors; /* 1440k @300rpm = 100ms + ~10ms/sector + 4ms/tr */ else - ms += 8 + (num_sectors<<1); /* 360k @360rpm = 83ms + ~20ms/sector + 3ms/tr */ + ms += 8 + (numsectors<<1); /* 360k @360rpm = 83ms + ~20ms/sector + 3ms/tr */ unsigned long timeout = jiffies + ms*HZ/100; while (!time_after(jiffies, timeout)) continue; #endif debug_cache("%s%d %lu(CHS %u,%u,%u-%u)\n", use_cache? "TR": (command == FD_WRITE? "WR": "RD"), current_drive, CURRENT->rq_sector>>1, track, head, - startsector + 1, startsector + num_sectors); -#endif + startsector + 1, startsector + numsectors); do_floppy = rw_interrupt; setup_DMA(); output_byte(command); @@ -1183,7 +1179,7 @@ static void DFPROC redo_fd_request(void) } } DEBUG("[%u]redo-%c %d(%s) bl %u;", (unsigned int)jiffies, - req->rq_cmd == WRITE? 'W':'R', device, floppy->name, req->rq_sector); + req->rq_cmd == WRITE? 'W':'R', drive, floppy->name, req->rq_sector); if (current_drive != drive) { current_track = NO_TRACK; @@ -1205,21 +1201,25 @@ static void DFPROC redo_fd_request(void) use_cache = (command == FD_READ) && (req->rq_errors < 4) && (floppy->sect <= MAX_BUFFER_SECTORS); #endif + startsector = (use_cache && FULL_TRACK)? 0: sector; + /* If the floppy sector count is odd, we cache one more sector + * when head=0 to get an even number of sectors (full blocks). + */ + numsectors = use_cache? + floppy->sect + (floppy->sect & 1 && !head) - startsector + : req->rq_nr_sectors; + DEBUG("df%d: %s sector %d CHS %d/%d/%d max %d stretch %d seek %d\n", DEVICE_NR(req->rq_dev), req->rq_cmd==READ? "read": "write", start, track, head, sector+1, floppy->sect, floppy->stretch, seek_track); - DEBUG("prep %d|%d,%d|%d-", cache_track, seek_track, cache_drive, current_drive); + DEBUG("prep %u|%d,%d|%d-", start, seek_track, cache_drive, current_drive); - if (cache_drive == current_drive && cache_track == ((seek_track << 1) + head) - && sector >= cache_startsector) { - /* Requested block is in the buffer. If reading, go get it. - * If the sector count is odd, we buffer sectors+1 when head=0 to get an even - * number of sectors (full blocks). When head=1 we read the entire track. - */ + if (cache_drive == current_drive && + start >= cache_start && start < cache_start + cache_numsectors) { DEBUG("cache CHS %d/%d/%d\n", seek_track, head, sector); debug_cache2("CH %d ", start >> 1); - cache_offset = (char *)(((sector - cache_startsector) << 9) + CACHE_OFF); + cache_offset = (char *)(((start - cache_start) << 9) + CACHE_OFF); if (command == FD_READ) { /* cache hit, no I/O necessary */ xms_fmemcpyw(req->rq_buffer, req->rq_seg, cache_offset, CACHE_SEG, BLOCK_SIZE/2); diff --git a/elks/init/main.c b/elks/init/main.c index f3c3750c2..612035bfe 100644 --- a/elks/init/main.c +++ b/elks/init/main.c @@ -211,7 +211,7 @@ static void INITPROC kernel_init(void) static void INITPROC kernel_banner(seg_t init, seg_t extra) { #ifdef CONFIG_ARCH_IBMPC - printk("PC/%cT class arch %d, ", (sys_caps & CAP_PC_AT) ? 'A' : 'X', SETUP_CPU_TYPE); + printk("PC/%cT class cpu %d, ", (sys_caps & CAP_PC_AT) ? 'A' : 'X', SETUP_CPU_TYPE); #endif #ifdef CONFIG_ARCH_PC98 From 3f34ab7b0d9481f68f2c2ab34f7cac1887ea0df4 Mon Sep 17 00:00:00 2001 From: Greg Haerr Date: Wed, 6 Nov 2024 20:42:34 -0800 Subject: [PATCH 2/4] Add TRACK_SPLIT_BLK option --- elks/arch/i86/drivers/block/directfd.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/elks/arch/i86/drivers/block/directfd.c b/elks/arch/i86/drivers/block/directfd.c index 7b9e3857f..9d614a774 100644 --- a/elks/arch/i86/drivers/block/directfd.c +++ b/elks/arch/i86/drivers/block/directfd.c @@ -129,6 +129,7 @@ char USE_IMPLIED_SEEK = 0; /* =1 for QEMU with 360k/AT stretch floppies (not rea #define CHECK_DIR_REG 1 /* =1 to read and clear DIR DSKCHG when media changed */ #define CHECK_DISK_CHANGE 1 /* =1 to inform kernel of media changed */ #define FULL_TRACK 1 /* =1 to read full tracks when track caching */ +#define TRACK_SPLIT_BLK 1 /* =1 to read extra sector on track split block */ #define IODELAY 0 /* =1 to emulate delay for floppy on QEMU */ /* adjustable timeouts */ @@ -484,7 +485,6 @@ static void DFPROC setup_DMA(void) if (use_bounce) { dma_addr = LINADDR(BOUNCE_SEG, BOUNCE_OFF); if (use_bounce && command == FD_WRITE) { - printk("XWRITE "); xms_fmemcpyw(BOUNCE_OFF, BOUNCE_SEG, req->rq_buffer, req->rq_seg, BLOCK_SIZE/2); } @@ -1197,17 +1197,24 @@ static void DFPROC redo_fd_request(void) track = tmp / floppy->head; seek_track = track << floppy->stretch; command = (req->rq_cmd == READ)? FD_READ: FD_WRITE; + startsector = sector; + numsectors = req->rq_nr_sectors; #ifdef CONFIG_TRACK_CACHE use_cache = (command == FD_READ) && (req->rq_errors < 4) && (floppy->sect <= MAX_BUFFER_SECTORS); + if (use_cache) { + if (FULL_TRACK) + startsector = 0; +#if TRACK_SPLIT_BLK + /* If the floppy sector count is odd, we cache one more sector + * when head=0 to get an even number of sectors (full blocks). + */ + numsectors = floppy->sect + (floppy->sect & 1 && !head) - startsector; +#else + numsectors = floppy->sect - startsector; +#endif + } #endif - startsector = (use_cache && FULL_TRACK)? 0: sector; - /* If the floppy sector count is odd, we cache one more sector - * when head=0 to get an even number of sectors (full blocks). - */ - numsectors = use_cache? - floppy->sect + (floppy->sect & 1 && !head) - startsector - : req->rq_nr_sectors; DEBUG("df%d: %s sector %d CHS %d/%d/%d max %d stretch %d seek %d\n", DEVICE_NR(req->rq_dev), req->rq_cmd==READ? "read": "write", From 17a982867b562a1cdbcab2837e6a949d1b7cc2cc Mon Sep 17 00:00:00 2001 From: Greg Haerr Date: Wed, 6 Nov 2024 21:16:26 -0800 Subject: [PATCH 3/4] Add MOTORDELAY; change IODELAY effective only on QEMU --- elks/arch/i86/drivers/block/directfd.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/elks/arch/i86/drivers/block/directfd.c b/elks/arch/i86/drivers/block/directfd.c index 9d614a774..770db78e0 100644 --- a/elks/arch/i86/drivers/block/directfd.c +++ b/elks/arch/i86/drivers/block/directfd.c @@ -130,6 +130,7 @@ char USE_IMPLIED_SEEK = 0; /* =1 for QEMU with 360k/AT stretch floppies (not rea #define CHECK_DISK_CHANGE 1 /* =1 to inform kernel of media changed */ #define FULL_TRACK 1 /* =1 to read full tracks when track caching */ #define TRACK_SPLIT_BLK 1 /* =1 to read extra sector on track split block */ +#define MOTORDELAY 0 /* =1 to emulate motor on delay for floppy on QEMU */ #define IODELAY 0 /* =1 to emulate delay for floppy on QEMU */ /* adjustable timeouts */ @@ -419,7 +420,8 @@ static void DFPROC floppy_on(int nr) if (!(mask & current_DOR)) { /* motor not running yet */ del_timer(&motor_on_timer[nr]); /* TEAC 1.44M says 'waiting time' 505ms, may be too little for 5.25in drives. */ - motor_on_timer[nr].tl_expires = jiffies + TIMEOUT_MOTOR_ON; + motor_on_timer[nr].tl_expires = jiffies + + ((running_qemu && !MOTORDELAY)? 0: TIMEOUT_MOTOR_ON); add_timer(&motor_on_timer[nr]); current_DOR &= 0xFC; /* remove drive select */ @@ -763,15 +765,17 @@ static void DFPROC setup_rw_floppy(void) DEBUG("setup_rw-"); #if IODELAY - static unsigned lasttrack; - unsigned ms = abs(track - lasttrack) * 4 / 10; - lasttrack = track; - if (current_drive == 0) - ms += 10 + numsectors; /* 1440k @300rpm = 100ms + ~10ms/sector + 4ms/tr */ - else - ms += 8 + (numsectors<<1); /* 360k @360rpm = 83ms + ~20ms/sector + 3ms/tr */ - unsigned long timeout = jiffies + ms*HZ/100; - while (!time_after(jiffies, timeout)) continue; + if (running_qemu) { + static unsigned lasttrack; + unsigned ms = abs(track - lasttrack) * 4 / 10; + lasttrack = track; + if (current_drive == 0) + ms += 10 + numsectors; /* 1440k @300rpm = 100ms + ~10ms/sector + 4ms/tr */ + else + ms += 8 + (numsectors<<1); /* 360k @360rpm = 83ms + ~20ms/sector + 3ms/tr */ + unsigned long timeout = jiffies + ms*HZ/100; + while (!time_after(jiffies, timeout)) continue; + } #endif debug_cache("%s%d %lu(CHS %u,%u,%u-%u)\n", use_cache? "TR": (command == FD_WRITE? "WR": "RD"), From aa4f6a8f1c5e2b8c5b6472e8c48d7d099763852b Mon Sep 17 00:00:00 2001 From: Greg Haerr Date: Wed, 6 Nov 2024 21:20:38 -0800 Subject: [PATCH 4/4] Cleanup --- elks/arch/i86/drivers/block/directfd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elks/arch/i86/drivers/block/directfd.c b/elks/arch/i86/drivers/block/directfd.c index 770db78e0..bd1cfa889 100644 --- a/elks/arch/i86/drivers/block/directfd.c +++ b/elks/arch/i86/drivers/block/directfd.c @@ -732,7 +732,7 @@ static void rw_interrupt(void) if (use_cache) { cache_drive = current_drive; /* cache now valid */ start = (unsigned int)req->rq_sector; - cache_start = FULL_TRACK? start - sector: start; + cache_start = (FULL_TRACK? start - sector: start); cache_numsectors = numsectors; cache_offset = (char *)(((start - cache_start) << 9) + CACHE_OFF); DEBUG("rd %04x:%04x->%08lx:%04x;", CACHE_SEG, cache_offset,