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

[directfd] Update DF driver for bugs on multiple opens #2087

Merged
merged 1 commit into from
Oct 25, 2024
Merged
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
69 changes: 35 additions & 34 deletions elks/arch/i86/drivers/block/directfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,34 +263,27 @@ static unsigned char p2880k[] = { FT_2880k, FT_1440k, 0 };
*/
static unsigned char *probe_list[CMOS_MAX] = { p360k, p1200k, p720k, p1440k, p2880k };

/* Auto-detection: disk type determined from CMOS and probing */
static struct floppy_struct *current_type[2];

/* initial probe per drive */
static unsigned char *base_type[2];

/*
* The driver is trying to determine the correct media format
* while probing is set. rw_interrupt() clears it after a
* successful access.
* The following variables must exist in duality, one for each drive.
*/
static int probing;

/* device reference counters */
static int fd_ref[2];
static int access_count;

/* bit vector set when media changed - causes I/O to be discarded until unset */
static unsigned int changed_floppies;
/* Auto-detection: disk type determined from CMOS and probing */
static struct floppy_struct *current_type[2];
static unsigned char *base_type[2]; /* initial probe per drive */
static int fd_ref[2]; /* ref count for invalidating buffers */
static int fd_probe[2]; /* set by open routine to start probing */
static struct inode *fd_inode[2]; /* for inode->i_size set after probe */

/*
* These are global variables, as that's the easiest way to pass info
* to interrupts. They are the data used for the current request.
*/
#define NO_TRACK 255

static bool use_cache; /* expand read request to fill cache when set */
static int use_bounce; /* XMS I/O or 64k address wrap or not caching when set */
static int access_count; /* ref count for deregistering driver */
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;
Expand All @@ -306,7 +299,6 @@ static unsigned char seek_track;
static unsigned char current_track = NO_TRACK;
static unsigned char command;
static unsigned char fdc_version;
static struct inode *open_inode; /* to reset inode->i_size after probe */

static void DFPROC floppy_ready(void);
static void DFPROC redo_fd_request(void);
Expand Down Expand Up @@ -505,7 +497,7 @@ static void DFPROC setup_DMA(void)
}
DEBUG("%d/%lx;", count, dma_addr);

clr_irq(); /* FIXME unclear interrupts need to be disabled */
clr_irq();
outb(FLOPPY_DMA | 4, DMA_INIT); /* disable floppy dma channel */
outb(0, DMA_FLIPFLOP); /* reset flip flop */
outb(FLOPPY_DMA | (command==FD_READ? DMA_MODE_READ : DMA_MODE_WRITE), DMA_MODE);
Expand Down Expand Up @@ -614,7 +606,7 @@ static void DFPROC perpendicular_mode(unsigned char rate)
reset = 1;
}
}
} /* perpendicular_mode */
}

static void DFPROC configure_fdc_mode(void)
{
Expand All @@ -625,12 +617,12 @@ static void DFPROC configure_fdc_mode(void)
output_byte(FD_CONFIGURE);
output_byte(0);
if (implied_seek)
output_byte(0x4A); /* FIFO on, polling on, 10 byte threshold, implied seek */
output_byte(0x4A); /* FIFO on, polling on, 10 byte threshold, implied seek */
else
output_byte(0x0A); /* FIFO on, polling on, 10 byte threshold */
output_byte(0); /* precompensation from track 0 upwards */
if (need_configure)
printk("df: implied seek %s\n", implied_seek? "enabled": "disabled");
DEBUG("df: implied seek %s\n", implied_seek? "enabled": "disabled");
need_configure = 0;
}
if (cur_spec1 != floppy->spec1) {
Expand All @@ -644,7 +636,7 @@ static void DFPROC configure_fdc_mode(void)
perpendicular_mode(floppy->rate);
outb_p((cur_rate = (floppy->rate)) & ~0x40, FD_CCR);
}
} /* configure_fdc_mode */
}

static void DFPROC tell_sector(int nr)
{
Expand All @@ -654,7 +646,7 @@ static void DFPROC tell_sector(int nr)
} else
printk(": track %d, head %d, sector %d", reply_buffer[3],
reply_buffer[4], reply_buffer[5]);
} /* tell_sector */
}

/*
* Ok, this interrupt is called after a DMA read/write has succeeded
Expand Down Expand Up @@ -714,8 +706,9 @@ static void rw_interrupt(void)
redo_fd_request();
return;
case 2: /* invalid command given */
printk("df: Invalid FDC command\n");
DEBUG("df: Invalid FDC command\n");
request_done(0);
redo_fd_request();
return;
case 3:
printk("df: Abnormal cmd termination\n");
Expand All @@ -727,10 +720,10 @@ static void rw_interrupt(void)
}

if (probing) {
open_inode->i_size = (sector_t)floppy->size << 9;
nr = DEVICE_NR(req->rq_dev);
printk("df%d: auto-detected floppy type %s\n", nr, floppy->name);
printk("df%d: floppy type %s\n", nr, floppy->name);
current_type[nr] = floppy;
fd_inode[nr]->i_size = (sector_t)floppy->size << 9;
probing = 0;
}
if (use_cache) {
Expand Down Expand Up @@ -1042,6 +1035,9 @@ void fake_disk_change(void)
}
#endif

/* bit vector set when media changed - causes I/O to be discarded until unset */
static unsigned int changed_floppies;

int check_disk_change(kdev_t dev)
{
unsigned int mask;
Expand Down Expand Up @@ -1156,6 +1152,10 @@ static void DFPROC redo_fd_request(void)
seek = 0;
type = MINOR(req->rq_dev);
drive = DEVICE_NR(type);
if (fd_probe[drive]) {
probing = 1;
fd_probe[drive] = 0;
}

#if CHECK_DISK_CHANGE
if (changed_floppies & (1 << drive)) {
Expand All @@ -1174,11 +1174,11 @@ static void DFPROC redo_fd_request(void)
if (!tmp) {
printk("df%d: Unable to determine drive type\n", drive);
request_done(0);
probing = 1;
fd_probe[drive] = 1;
goto repeat;
}
floppy = &minor_types[tmp];
if (!recalibrate && probing)
if (!recalibrate && probing > 1)
printk("df%d: auto-probe #%d %s\n", drive, probing, floppy->name);
}
}
Expand Down Expand Up @@ -1326,15 +1326,16 @@ static int floppy_open(struct inode *inode, struct file *filp)
}
#endif

probing = 0;
fd_probe[drive] = 0;
if (type > 1 && type < MAX_MINOR) /* forced floppy type */
floppy = &minor_types[type >> 1];
else { /* Auto-detection */
floppy = current_type[drive];
if (!floppy) {
if (!base_type[drive])
return -ENXIO;
probing = 1;
if (sys_caps & CAP_PC_AT) /* don't probe XT systems */
fd_probe[drive] = 1;
floppy = &minor_types[base_type[drive][0]];
}
}
Expand All @@ -1347,8 +1348,8 @@ static int floppy_open(struct inode *inode, struct file *filp)

access_count++;
fd_ref[drive]++;
inode->i_size = (sector_t)floppy->size << 9; /* NOTE: assumes sector size 512 */
open_inode = inode;
fd_inode[drive] = inode;
inode->i_size = (sector_t)floppy->size << 9; /* NOTE: may change value after probe */
DEBUG("df%d: open %s, size %lu\n", drive, floppy->name, inode->i_size);

return 0;
Expand Down
Loading