[int13] Pairwise swap drive numbers, instead of shifting all drive numbers
[people/mcb30/gpxe.git] / src / arch / i386 / include / int13.h
1 #ifndef INT13_H
2 #define INT13_H
3
4 /** @file
5  *
6  * INT 13 emulation
7  *
8  */
9
10 #include <stdint.h>
11 #include <gpxe/list.h>
12
13 struct block_device;
14
15 /**
16  * @defgroup int13ops INT 13 operation codes
17  * @{
18  */
19
20 /** Reset disk system */
21 #define INT13_RESET                     0x00
22 /** Get status of last operation */
23 #define INT13_GET_LAST_STATUS           0x01
24 /** Read sectors */
25 #define INT13_READ_SECTORS              0x02
26 /** Write sectors */
27 #define INT13_WRITE_SECTORS             0x03
28 /** Get drive parameters */
29 #define INT13_GET_PARAMETERS            0x08
30 /** Get disk type */
31 #define INT13_GET_DISK_TYPE             0x15
32 /** Extensions installation check */
33 #define INT13_EXTENSION_CHECK           0x41
34 /** Extended read */
35 #define INT13_EXTENDED_READ             0x42
36 /** Extended write */
37 #define INT13_EXTENDED_WRITE            0x43
38 /** Get extended drive parameters */
39 #define INT13_GET_EXTENDED_PARAMETERS   0x48
40 /** Get CD-ROM status / terminate emulation */
41 #define INT13_CDROM_STATUS_TERMINATE    0x4b
42
43 /** @} */
44
45 /**
46  * @defgroup int13status INT 13 status codes
47  * @{
48  */
49
50 /** Operation completed successfully */
51 #define INT13_STATUS_SUCCESS            0x00
52 /** Invalid function or parameter */
53 #define INT13_STATUS_INVALID            0x01
54 /** Read error */
55 #define INT13_STATUS_READ_ERROR         0x04
56 /** Write error */
57 #define INT13_STATUS_WRITE_ERROR        0xcc
58
59 /** @} */
60
61 /** Block size for non-extended INT 13 calls */
62 #define INT13_BLKSIZE 512
63
64 /** An INT 13 emulated drive */
65 struct int13_drive {
66         /** List of all registered drives */
67         struct list_head list;
68
69         /** Underlying block device */
70         struct block_device *blockdev;
71
72         /** BIOS in-use drive number (0x80-0xff) */
73         unsigned int drive;
74         /** BIOS natural drive number (0x80-0xff)
75          *
76          * This is the drive number that would have been assigned by
77          * 'naturally' appending the drive to the end of the BIOS
78          * drive list.
79          *
80          * If the emulated drive replaces a preexisting drive, this is
81          * the drive number that the preexisting drive gets remapped
82          * to.
83          */
84         unsigned int natural_drive;
85
86         /** Number of cylinders
87          *
88          * The cylinder number field in an INT 13 call is ten bits
89          * wide, giving a maximum of 1024 cylinders.  Conventionally,
90          * when the 7.8GB limit of a CHS address is exceeded, it is
91          * the number of cylinders that is increased beyond the
92          * addressable limit.
93          */
94         unsigned int cylinders;
95         /** Number of heads
96          *
97          * The head number field in an INT 13 call is eight bits wide,
98          * giving a maximum of 256 heads.  However, apparently all
99          * versions of MS-DOS up to and including Win95 fail with 256
100          * heads, so the maximum encountered in practice is 255.
101          */
102         unsigned int heads;
103         /** Number of sectors per track
104          *
105          * The sector number field in an INT 13 call is six bits wide,
106          * giving a maximum of 63 sectors, since sector numbering
107          * (unlike head and cylinder numbering) starts at 1, not 0.
108          */
109         unsigned int sectors_per_track;
110
111         /** Status of last operation */
112         int last_status;
113 };
114
115 /** An INT 13 disk address packet */
116 struct int13_disk_address {
117         /** Size of the packet, in bytes */
118         uint8_t bufsize;
119         /** Reserved, must be zero */
120         uint8_t reserved;
121         /** Block count */
122         uint16_t count;
123         /** Data buffer */
124         struct segoff buffer;
125         /** Starting block number */
126         uint64_t lba;
127         /** Data buffer (EDD-3.0 only) */
128         uint64_t buffer_phys;
129 } __attribute__ (( packed ));
130
131 /** INT 13 disk parameters */
132 struct int13_disk_parameters {
133         /** Size of this structure */
134         uint16_t bufsize;
135         /** Flags */
136         uint16_t flags;
137         /** Number of cylinders */
138         uint32_t cylinders;
139         /** Number of heads */
140         uint32_t heads;
141         /** Number of sectors per track */
142         uint32_t sectors_per_track;
143         /** Total number of sectors on drive */
144         uint64_t sectors;
145         /** Bytes per sector */
146         uint16_t sector_size;
147         
148 } __attribute__ (( packed ));
149
150 /**
151  * @defgroup int13types INT 13 disk types
152  * @{
153  */
154
155 /** No such drive */
156 #define INT13_DISK_TYPE_NONE    0x00
157 /** Floppy without change-line support */
158 #define INT13_DISK_TYPE_FDD     0x01
159 /** Floppy with change-line support */
160 #define INT13_DISK_TYPE_FDD_CL  0x02
161 /** Hard disk */
162 #define INT13_DISK_TYPE_HDD     0x03
163
164 /** @} */
165
166 /**
167  * @defgroup int13flags INT 13 disk parameter flags
168  * @{
169  */
170
171 /** DMA boundary errors handled transparently */
172 #define INT13_FL_DMA_TRANSPARENT 0x01
173 /** CHS information is valid */
174 #define INT13_FL_CHS_VALID       0x02
175 /** Removable drive */
176 #define INT13_FL_REMOVABLE       0x04
177 /** Write with verify supported */
178 #define INT13_FL_VERIFIABLE      0x08
179 /** Has change-line supported (valid only for removable drives) */
180 #define INT13_FL_CHANGE_LINE     0x10
181 /** Drive can be locked (valid only for removable drives) */
182 #define INT13_FL_LOCKABLE        0x20
183 /** CHS is max possible, not current media (valid only for removable drives) */
184 #define INT13_FL_CHS_MAX         0x40
185
186 /** @} */
187
188 /**
189  * @defgroup int13exts INT 13 extension flags
190  * @{
191  */
192
193 /** Extended disk access functions supported */
194 #define INT13_EXTENSION_LINEAR          0x01
195 /** Removable drive functions supported */
196 #define INT13_EXTENSION_REMOVABLE       0x02
197 /** EDD functions supported */
198 #define INT13_EXTENSION_EDD             0x04
199
200 /** @} */
201
202 /**
203  * @defgroup int13vers INT 13 extension versions
204  * @{
205  */
206
207 /** INT13 extensions version 1.x */
208 #define INT13_EXTENSION_VER_1_X         0x01
209 /** INT13 extensions version 2.0 (EDD-1.0) */
210 #define INT13_EXTENSION_VER_2_0         0x20
211 /** INT13 extensions version 2.1 (EDD-1.1) */
212 #define INT13_EXTENSION_VER_2_1         0x21
213 /** INT13 extensions version 3.0 (EDD-3.0) */
214 #define INT13_EXTENSION_VER_3_0         0x30
215
216 /** @} */ 
217
218 /** Bootable CD-ROM specification packet */
219 struct int13_cdrom_specification {
220         /** Size of packet in bytes */
221         uint8_t size;
222         /** Boot media type */
223         uint8_t media_type;
224         /** Drive number */
225         uint8_t drive;
226         /** CD-ROM controller number */
227         uint8_t controller;
228         /** LBA of disk image to emulate */
229         uint32_t lba;
230         /** Device specification */
231         uint16_t device;
232         /** Segment of 3K buffer for caching CD-ROM reads */
233         uint16_t cache_segment;
234         /** Load segment for initial boot image */
235         uint16_t load_segment;
236         /** Number of 512-byte sectors to load */
237         uint16_t load_sectors;
238         /** Low 8 bits of cylinder number */
239         uint8_t cyl;
240         /** Sector number, plus high 2 bits of cylinder number */
241         uint8_t cyl_sector;
242         /** Head number */
243         uint8_t head;
244 } __attribute__ (( packed ));
245
246 /** A C/H/S address within a partition table entry */
247 struct partition_chs {
248         /** Head number */
249         uint8_t head;
250         /** Sector number, plus high 2 bits of cylinder number */
251         uint8_t cyl_sector;
252         /** Low 8 bits of cylinder number */
253         uint8_t cyl;
254 } __attribute__ (( packed ));
255
256 #define PART_HEAD(chs) ( (chs).head )
257 #define PART_SECTOR(chs) ( (chs).cyl_sector & 0x3f )
258 #define PART_CYLINDER(chs) ( (chs).cyl | ( ( (chs).cyl_sector & 0xc0 ) << 2 ) )
259
260 /** A partition table entry within the MBR */
261 struct partition_table_entry {
262         /** Bootable flag */
263         uint8_t bootable;
264         /** C/H/S start address */
265         struct partition_chs chs_start;
266         /** System indicator (partition type) */
267         uint8_t type;
268         /** C/H/S end address */
269         struct partition_chs chs_end;
270         /** Linear start address */
271         uint32_t start;
272         /** Linear length */
273         uint32_t length;
274 } __attribute__ (( packed ));
275
276 /** A Master Boot Record */
277 struct master_boot_record {
278         uint8_t pad[446];
279         /** Partition table */
280         struct partition_table_entry partitions[4];
281         /** 0x55aa MBR signature */
282         uint16_t signature;
283 } __attribute__ (( packed ));
284
285 extern void register_int13_drive ( struct int13_drive *drive );
286 extern void unregister_int13_drive ( struct int13_drive *drive );
287 extern int int13_boot ( unsigned int drive );
288
289 #endif /* INT13_H */