Skip to content

Commit

Permalink
[directfd] Update DF driver for bugs on multiple opens
Browse files Browse the repository at this point in the history
  • Loading branch information
ghaerr committed Oct 25, 2024
1 parent 81f639b commit 48ff74a
Showing 1 changed file with 35 additions and 34 deletions.
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

0 comments on commit 48ff74a

Please sign in to comment.