diff options
Diffstat (limited to 'drivers/block/floppy.c')
-rw-r--r-- | drivers/block/floppy.c | 44 |
1 files changed, 28 insertions, 16 deletions
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 8823e4c97..088980ead 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -534,6 +534,8 @@ static struct floppy_struct *_floppy = floppy_type; static unsigned char current_drive = 0; static long current_count_sectors = 0; static unsigned char sector_t; /* sector in track */ +static unsigned char in_sector_offset; /* offset within physical sector, + * expressed in units of 512 bytes */ #ifndef fd_eject #define fd_eject(x) -EINVAL @@ -2252,7 +2254,7 @@ static void request_done(int uptodate) /* Interrupt handler evaluating the result of the r/w operation */ static void rw_interrupt(void) { - int nr_sectors, ssize, eoc; + int nr_sectors, ssize, eoc, heads; if (!DRS->first_read_date) DRS->first_read_date = jiffies; @@ -2264,23 +2266,32 @@ static void rw_interrupt(void) eoc = 1; else eoc = 0; - nr_sectors = ((R_TRACK-TRACK)*_floppy->head+R_HEAD-HEAD) * - _floppy->sect + ((R_SECTOR-SECTOR+eoc) << SIZECODE >> 2) - - (sector_t % _floppy->sect) % ssize; + + if(COMMAND & 0x80) + heads = 2; + else + heads = 1; + + nr_sectors = (((R_TRACK-TRACK) * heads + + R_HEAD-HEAD) * SECT_PER_TRACK + + R_SECTOR-SECTOR + eoc) << SIZECODE >> 2; #ifdef FLOPPY_SANITY_CHECK - if (nr_sectors > current_count_sectors + ssize - - (current_count_sectors + sector_t) % ssize + - sector_t % ssize){ + if (nr_sectors / ssize > + (in_sector_offset + current_count_sectors + ssize - 1)/ssize) { DPRINT("long rw: %x instead of %lx\n", nr_sectors, current_count_sectors); printk("rs=%d s=%d\n", R_SECTOR, SECTOR); printk("rh=%d h=%d\n", R_HEAD, HEAD); printk("rt=%d t=%d\n", R_TRACK, TRACK); - printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK, - sector_t, ssize); + printk("heads=%d eoc=%d\n", heads, eoc); + printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK, + sector_t, ssize); + printk("in_sector_offset=%d\n", in_sector_offset); } #endif + + nr_sectors -= in_sector_offset; INFBOUND(nr_sectors,0); SUPBOUND(current_count_sectors, nr_sectors); @@ -2473,7 +2484,7 @@ static inline int check_dma_crossing(char *start, * does not work with MT, hence we can only transfer one head at * a time */ -static int virtualdmabug_workaround() { +static void virtualdmabug_workaround(void) { int hard_sectors, end_sector; if(CT(COMMAND) == FD_WRITE) { COMMAND &= ~0x80; /* switch off multiple track mode */ @@ -2484,7 +2495,7 @@ static int virtualdmabug_workaround() { if(end_sector > SECT_PER_TRACK) { printk("too many sectors %d > %d\n", end_sector, SECT_PER_TRACK); - return 0; + return; } #endif SECT_PER_TRACK = end_sector; /* make sure SECT_PER_TRACK points @@ -2595,7 +2606,8 @@ static int make_raw_rw_request(void) max_sector = _floppy->sect; } - aligned_sector_t = sector_t - (sector_t % _floppy->sect) % ssize; + in_sector_offset = (sector_t % _floppy->sect) % ssize; + aligned_sector_t = sector_t - in_sector_offset; max_size = CURRENT->nr_sectors; if ((raw_cmd->track == buffer_track) && (current_drive == buffer_drive) && @@ -2605,7 +2617,7 @@ static int make_raw_rw_request(void) copy_buffer(1, max_sector, buffer_max); return 1; } - } else if (aligned_sector_t != sector_t || CURRENT->nr_sectors < ssize){ + } else if (in_sector_offset || CURRENT->nr_sectors < ssize){ if (CT(COMMAND) == FD_WRITE){ if (sector_t + CURRENT->nr_sectors > ssize && sector_t + CURRENT->nr_sectors < ssize + ssize) @@ -2677,7 +2689,7 @@ static int make_raw_rw_request(void) sector_t > buffer_max || sector_t < buffer_min || ((CT(COMMAND) == FD_READ || - (aligned_sector_t == sector_t && CURRENT->nr_sectors >= ssize))&& + (!in_sector_offset && CURRENT->nr_sectors >= ssize))&& max_sector > 2 * max_buffer_sectors + buffer_min && max_size + sector_t > 2 * max_buffer_sectors + buffer_min) /* not enough space */){ @@ -2694,7 +2706,7 @@ static int make_raw_rw_request(void) * is either aligned or the data already in the buffer * (buffer will be overwritten) */ #ifdef FLOPPY_SANITY_CHECK - if (sector_t != aligned_sector_t && buffer_track == -1) + if (in_sector_offset && buffer_track == -1) DPRINT("internal error offset !=0 on write\n"); #endif buffer_track = raw_cmd->track; @@ -2705,7 +2717,7 @@ static int make_raw_rw_request(void) 2*max_buffer_sectors+buffer_min-aligned_sector_t); /* round up current_count_sectors to get dma xfer size */ - raw_cmd->length = sector_t+current_count_sectors-aligned_sector_t; + raw_cmd->length = in_sector_offset+current_count_sectors; raw_cmd->length = ((raw_cmd->length -1)|(ssize-1))+1; raw_cmd->length <<= 9; #ifdef FLOPPY_SANITY_CHECK |