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

[direct floppy] Revise cache numbering scheme for more flexibility #2096

Merged
merged 4 commits into from
Nov 7, 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
87 changes: 49 additions & 38 deletions elks/arch/i86/drivers/block/directfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ 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 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 */
Expand Down Expand Up @@ -285,13 +287,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;
Expand Down Expand Up @@ -417,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 */
Expand Down Expand Up @@ -475,26 +479,24 @@ 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) {
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
} else
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();
Expand Down Expand Up @@ -657,6 +659,7 @@ static void rw_interrupt(void)
{
struct request *req = CURRENT;
int nr, bad;
unsigned int start;
char *cache_offset;

nr = result();
Expand Down Expand Up @@ -728,9 +731,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);
Expand Down Expand Up @@ -759,28 +763,24 @@ 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 */
else
ms += 8 + (num_sectors<<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"),
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);
Expand Down Expand Up @@ -1183,7 +1183,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;
Expand All @@ -1201,25 +1201,36 @@ 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

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);
Expand Down
2 changes: 1 addition & 1 deletion elks/init/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading