xref: /aosp_15_r20/external/mtools/lba.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
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 Hughes int 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