1 /* Copyright 2021 Alain Knaff. 2 * This file is part of mtools. 3 * 4 * Mtools is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * Mtools is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with Mtools. If not, see <http://www.gnu.org/licenses/>. 16 * 17 * "LBA Assist" geometry 18 */ 19 20 #include "sysincludes.h" 21 #include "mtools.h" 22 #include "lba.h" 23 compute_lba_geom_from_tot_sectors(struct device * dev)24int compute_lba_geom_from_tot_sectors(struct device *dev) 25 { 26 unsigned int sect_per_track; 27 uint32_t tracks; 28 29 /* If already fully specified, nothing to do */ 30 if(dev->heads && dev->sectors && dev->tracks) 31 return 0; 32 33 /* If tot_sectors missing, return. Hopefully size still 34 * specified somewhere that will be read at a later stage 35 * (such as mformat command line) */ 36 if(dev->tot_sectors == 0) { 37 return 0; 38 } 39 40 /* Floppy sizes, allowing for non-standard sizes with slightly 41 more sectors per track than the default */ 42 if(dev->tot_sectors && 43 dev->tot_sectors <= 8640 && dev->tot_sectors % 40 == 0) { 44 if(dev->tot_sectors <= 540) { 45 /* double density 48tpi single sided */ 46 dev->tracks = 40; 47 dev->heads = 1; 48 } else if(dev->tot_sectors <= 1080) { 49 /* double density 48tpi double sided or 50 96 tpi single sided */ 51 52 if(dev->heads == 1) 53 dev->tracks = 80; 54 else { 55 dev->tracks = 40; 56 dev->heads = 2; 57 } 58 } else { 59 /* double density 96tpi double sided, 60 * high density, extra density */ 61 dev->tracks = 80; 62 dev->heads = 2; 63 } 64 dev->sectors = 65 (uint16_t)(dev->tot_sectors / dev->heads / dev->tracks); 66 } 67 68 69 /* Heads or sectors not known => fill them in both... */ 70 if(!dev->sectors || !dev->heads) { 71 dev->sectors = 63; 72 73 if (dev->tot_sectors < 16u*dev->sectors*1024) 74 dev->heads = 16; 75 else if (dev->tot_sectors < 32u*dev->sectors*1024) 76 dev->heads = 32; 77 else if (dev->tot_sectors < 64u*dev->sectors*1024) 78 dev->heads = 64; 79 else if (dev->tot_sectors < 128u*dev->sectors*1024) 80 dev->heads = 128; 81 else 82 dev->heads = 255; 83 } 84 85 /* ... and calculate corresponding tracks */ 86 if(!dev->tracks) { 87 sect_per_track = dev->heads * dev->sectors; 88 tracks = (dev->tot_sectors + sect_per_track - 1) / 89 sect_per_track; 90 dev->tracks = tracks; 91 } 92 93 return 0; 94 } 95