Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

floppy: support arbitrary first-sector numbers

The current floppy_struct allows floppies to number sectors starting
from 0 or 1. This patch allows arbitrary first-sector numbers - for
example, 0xC1 for Amstrad CPC disks.

This extends the existing 1-bit field (FD_ZEROBASED, bit 2 of stretch)
to 8 bits (FD_SECTMASK, bits 2 to 9).

Currently 0x00 denotes a first sector number of 1, and 0x01 denotes a
first sector number of 0. We extend this by interpreting FD_SECTMASK
as the first sector number with the LSB flipped.

Signed-off-by: Keith Wansbrough <keith@lochan.org>
Cc: Alain Knaff <alain@linux.lu>
Cc: Michael Kerrisk <mtk.manpages@googlemail.com>
Cc: Karel Zak <kzak@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>

authored by

Keith Wansbrough and committed by
Jens Axboe
9e49184c 061837bc

+22 -9
+15 -8
drivers/block/floppy.c
··· 423 423 * 1581's logical side 0 is on physical side 1, whereas the Sharp's logical 424 424 * side 0 is on physical side 0 (but with the misnamed sector IDs). 425 425 * 'stretch' should probably be renamed to something more general, like 426 - * 'options'. Other parameters should be self-explanatory (see also 427 - * setfdprm(8)). 426 + * 'options'. 427 + * 428 + * Bits 2 through 9 of 'stretch' tell the number of the first sector. 429 + * The LSB (bit 2) is flipped. For most disks, the first sector 430 + * is 1 (represented by 0x00<<2). For some CP/M and music sampler 431 + * disks (such as Ensoniq EPS 16plus) it is 0 (represented as 0x01<<2). 432 + * For Amstrad CPC disks it is 0xC1 (represented as 0xC0<<2). 433 + * 434 + * Other parameters should be self-explanatory (see also setfdprm(8)). 428 435 */ 429 436 /* 430 437 Size ··· 2243 2236 } 2244 2237 } 2245 2238 } 2246 - if (_floppy->stretch & FD_ZEROBASED) { 2239 + if (_floppy->stretch & FD_SECTBASEMASK) { 2247 2240 for (count = 0; count < F_SECT_PER_TRACK; count++) 2248 - here[count].sect--; 2241 + here[count].sect += FD_SECTBASE(_floppy) - 1; 2249 2242 } 2250 2243 } 2251 2244 ··· 2656 2649 } 2657 2650 HEAD = fsector_t / _floppy->sect; 2658 2651 2659 - if (((_floppy->stretch & (FD_SWAPSIDES | FD_ZEROBASED)) || 2652 + if (((_floppy->stretch & (FD_SWAPSIDES | FD_SECTBASEMASK)) || 2660 2653 TESTF(FD_NEED_TWADDLE)) && fsector_t < _floppy->sect) 2661 2654 max_sector = _floppy->sect; 2662 2655 ··· 2686 2679 CODE2SIZE; 2687 2680 SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE; 2688 2681 SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) + 2689 - ((_floppy->stretch & FD_ZEROBASED) ? 0 : 1); 2682 + FD_SECTBASE(_floppy); 2690 2683 2691 2684 /* tracksize describes the size which can be filled up with sectors 2692 2685 * of size ssize. ··· 3318 3311 g->head <= 0 || 3319 3312 g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) || 3320 3313 /* check if reserved bits are set */ 3321 - (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_ZEROBASED)) != 0) 3314 + (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_SECTBASEMASK)) != 0) 3322 3315 return -EINVAL; 3323 3316 if (type) { 3324 3317 if (!capable(CAP_SYS_ADMIN)) ··· 3363 3356 if (DRS->maxblock > user_params[drive].sect || 3364 3357 DRS->maxtrack || 3365 3358 ((user_params[drive].sect ^ oldStretch) & 3366 - (FD_SWAPSIDES | FD_ZEROBASED))) 3359 + (FD_SWAPSIDES | FD_SECTBASEMASK))) 3367 3360 invalidate_drive(bdev); 3368 3361 else 3369 3362 process_fd_request();
+7 -1
include/linux/fd.h
··· 15 15 sect, /* sectors per track */ 16 16 head, /* nr of heads */ 17 17 track, /* nr of tracks */ 18 - stretch; /* !=0 means double track steps */ 18 + stretch; /* bit 0 !=0 means double track steps */ 19 + /* bit 1 != 0 means swap sides */ 20 + /* bits 2..9 give the first sector */ 21 + /* number (the LSB is flipped) */ 19 22 #define FD_STRETCH 1 20 23 #define FD_SWAPSIDES 2 21 24 #define FD_ZEROBASED 4 25 + #define FD_SECTBASEMASK 0x3FC 26 + #define FD_MKSECTBASE(s) (((s) ^ 1) << 2) 27 + #define FD_SECTBASE(floppy) ((((floppy)->stretch & FD_SECTBASEMASK) >> 2) ^ 1) 22 28 23 29 unsigned char gap, /* gap1 size */ 24 30