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