Skip to content

Commit

Permalink
Merge pull request #2096 from ghaerr/df5
Browse files Browse the repository at this point in the history
[direct floppy] Revise cache numbering scheme for more flexibility
  • Loading branch information
ghaerr authored Nov 7, 2024
2 parents 6ce8caa + aa4f6a8 commit fd32d9f
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 39 deletions.
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

0 comments on commit fd32d9f

Please sign in to comment.