fix formatting
[reactos.git] / reactos / boot / freeldr / freeldr / arch / i386 / xboxdisk.c
1 /* $Id$
2 *
3 * FreeLoader
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * Note: mostly ripped from atapi.c
20 * Some of this code was based on knowledge and/or code developed
21 * by the Xbox Linux group: http://www.xbox-linux.org
22 *
23 */
24
25 #include <freeldr.h>
26
27 #define NDEBUG
28 #include <debug.h>
29
30 #define XBOX_IDE_COMMAND_PORT 0x1f0
31 #define XBOX_IDE_CONTROL_PORT 0x170
32
33 #define XBOX_SIGNATURE_SECTOR 3
34 #define XBOX_SIGNATURE ('B' | ('R' << 8) | ('F' << 16) | ('R' << 24))
35
36 static struct
37 {
38 ULONG SectorCountBeforePartition;
39 ULONG PartitionSectorCount;
40 UCHAR SystemIndicator;
41 } XboxPartitions[] =
42 {
43 /* This is in the \Device\Harddisk0\Partition.. order used by the Xbox kernel */
44 { 0x0055F400, 0x0098f800, PARTITION_FAT32 }, /* Store, E: */
45 { 0x00465400, 0x000FA000, PARTITION_FAT_16 }, /* System, C: */
46 { 0x00000400, 0x00177000, PARTITION_FAT_16 }, /* Cache1, X: */
47 { 0x00177400, 0x00177000, PARTITION_FAT_16 }, /* Cache2, Y: */
48 { 0x002EE400, 0x00177000, PARTITION_FAT_16 } /* Cache3, Z: */
49 };
50
51 #define IDE_SECTOR_BUF_SZ 512
52 #define IDE_MAX_POLL_RETRIES 100000
53 #define IDE_MAX_BUSY_RETRIES 50000
54
55 /* Control Block offsets and masks */
56 #define IDE_REG_ALT_STATUS 0x0000
57 #define IDE_REG_DEV_CNTRL 0x0000 /* device control register */
58 #define IDE_DC_SRST 0x04 /* drive reset (both drives) */
59 #define IDE_DC_nIEN 0x02 /* IRQ enable (active low) */
60 #define IDE_REG_DRV_ADDR 0x0001
61
62 /* Command Block offsets and masks */
63 #define IDE_REG_DATA_PORT 0x0000
64 #define IDE_REG_ERROR 0x0001 /* error register */
65 #define IDE_ER_AMNF 0x01 /* addr mark not found */
66 #define IDE_ER_TK0NF 0x02 /* track 0 not found */
67 #define IDE_ER_ABRT 0x04 /* command aborted */
68 #define IDE_ER_MCR 0x08 /* media change requested */
69 #define IDE_ER_IDNF 0x10 /* ID not found */
70 #define IDE_ER_MC 0x20 /* Media changed */
71 #define IDE_ER_UNC 0x40 /* Uncorrectable data error */
72 #define IDE_REG_PRECOMP 0x0001
73 #define IDE_REG_SECTOR_CNT 0x0002
74 #define IDE_REG_SECTOR_NUM 0x0003
75 #define IDE_REG_CYL_LOW 0x0004
76 #define IDE_REG_CYL_HIGH 0x0005
77 #define IDE_REG_DRV_HEAD 0x0006
78 #define IDE_DH_FIXED 0xA0
79 #define IDE_DH_LBA 0x40
80 #define IDE_DH_HDMASK 0x0F
81 #define IDE_DH_DRV0 0x00
82 #define IDE_DH_DRV1 0x10
83 #define IDE_REG_STATUS 0x0007
84 #define IDE_SR_BUSY 0x80
85 #define IDE_SR_DRDY 0x40
86 #define IDE_SR_WERR 0x20
87 #define IDE_SR_DRQ 0x08
88 #define IDE_SR_ERR 0x01
89 #define IDE_REG_COMMAND 0x0007
90
91 /* IDE/ATA commands */
92 #define IDE_CMD_RESET 0x08
93 #define IDE_CMD_READ 0x20
94 #define IDE_CMD_READ_RETRY 0x21
95 #define IDE_CMD_WRITE 0x30
96 #define IDE_CMD_WRITE_RETRY 0x31
97 #define IDE_CMD_PACKET 0xA0
98 #define IDE_CMD_READ_MULTIPLE 0xC4
99 #define IDE_CMD_WRITE_MULTIPLE 0xC5
100 #define IDE_CMD_READ_DMA 0xC8
101 #define IDE_CMD_WRITE_DMA 0xCA
102 #define IDE_CMD_FLUSH_CACHE 0xE7
103 #define IDE_CMD_FLUSH_CACHE_EXT 0xEA
104 #define IDE_CMD_IDENT_ATA_DRV 0xEC
105 #define IDE_CMD_IDENT_ATAPI_DRV 0xA1
106 #define IDE_CMD_GET_MEDIA_STATUS 0xDA
107
108 /*
109 * Access macros for command registers
110 * Each macro takes an address of the command port block, and data
111 */
112 #define IDEReadError(Address) \
113 (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_ERROR)))
114 #define IDEWritePrecomp(Address, Data) \
115 (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_PRECOMP), (Data)))
116 #define IDEReadSectorCount(Address) \
117 (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT)))
118 #define IDEWriteSectorCount(Address, Data) \
119 (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT), (Data)))
120 #define IDEReadSectorNum(Address) \
121 (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM)))
122 #define IDEWriteSectorNum(Address, Data) \
123 (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM), (Data)))
124 #define IDEReadCylinderLow(Address) \
125 (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW)))
126 #define IDEWriteCylinderLow(Address, Data) \
127 (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW), (Data)))
128 #define IDEReadCylinderHigh(Address) \
129 (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH)))
130 #define IDEWriteCylinderHigh(Address, Data) \
131 (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH), (Data)))
132 #define IDEReadDriveHead(Address) \
133 (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD)))
134 #define IDEWriteDriveHead(Address, Data) \
135 (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD), (Data)))
136 #define IDEReadStatus(Address) \
137 (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_STATUS)))
138 #define IDEWriteCommand(Address, Data) \
139 (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_COMMAND), (Data)))
140 #define IDEReadDMACommand(Address) \
141 (READ_PORT_UCHAR((PUCHAR)((Address))))
142 #define IDEWriteDMACommand(Address, Data) \
143 (WRITE_PORT_UCHAR((PUCHAR)((Address)), (Data)))
144 #define IDEReadDMAStatus(Address) \
145 (READ_PORT_UCHAR((PUCHAR)((Address) + 2)))
146 #define IDEWriteDMAStatus(Address, Data) \
147 (WRITE_PORT_UCHAR((PUCHAR)((Address) + 2), (Data)))
148 #define IDEWritePRDTable(Address, Data) \
149 (WRITE_PORT_ULONG((PULONG)((Address) + 4), (Data)))
150
151 /*
152 * Data block read and write commands
153 */
154 #define IDEReadBlock(Address, Buffer, Count) \
155 (__inwordstring(((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2))
156 #define IDEWriteBlock(Address, Buffer, Count) \
157 (WRITE_PORT_BUFFER_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2))
158
159 #define IDEReadBlock32(Address, Buffer, Count) \
160 (READ_PORT_BUFFER_ULONG((PULONG)((Address) + IDE_REG_DATA_PORT), (PULONG)(Buffer), (Count) / 4))
161 #define IDEWriteBlock32(Address, Buffer, Count) \
162 (WRITE_PORT_BUFFER_ULONG((PULONG)((Address) + IDE_REG_DATA_PORT), (PULONG)(Buffer), (Count) / 4))
163
164 #define IDEReadWord(Address) \
165 (READ_PORT_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT)))
166
167 /*
168 * Access macros for control registers
169 * Each macro takes an address of the control port blank and data
170 */
171 #define IDEReadAltStatus(Address) \
172 (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_ALT_STATUS)))
173 #define IDEWriteDriveControl(Address, Data) \
174 (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DEV_CNTRL), (Data)))
175
176 /* IDE_DRIVE_IDENTIFY */
177
178 typedef struct _IDE_DRIVE_IDENTIFY
179 {
180 USHORT ConfigBits; /*00*/
181 USHORT LogicalCyls; /*01*/
182 USHORT Reserved02; /*02*/
183 USHORT LogicalHeads; /*03*/
184 USHORT BytesPerTrack; /*04*/
185 USHORT BytesPerSector; /*05*/
186 USHORT SectorsPerTrack; /*06*/
187 UCHAR InterSectorGap; /*07*/
188 UCHAR InterSectorGapSize;
189 UCHAR Reserved08H; /*08*/
190 UCHAR BytesInPLO;
191 USHORT VendorUniqueCnt; /*09*/
192 char SerialNumber[20]; /*10*/
193 USHORT ControllerType; /*20*/
194 USHORT BufferSize; /*21*/
195 USHORT ECCByteCnt; /*22*/
196 char FirmwareRev[8]; /*23*/
197 char ModelNumber[40]; /*27*/
198 USHORT RWMultImplemented; /*47*/
199 USHORT DWordIo; /*48*/
200 USHORT Capabilities; /*49*/
201 #define IDE_DRID_STBY_SUPPORTED 0x2000
202 #define IDE_DRID_IORDY_SUPPORTED 0x0800
203 #define IDE_DRID_IORDY_DISABLE 0x0400
204 #define IDE_DRID_LBA_SUPPORTED 0x0200
205 #define IDE_DRID_DMA_SUPPORTED 0x0100
206 USHORT Reserved50; /*50*/
207 USHORT MinPIOTransTime; /*51*/
208 USHORT MinDMATransTime; /*52*/
209 USHORT TMFieldsValid; /*53*/
210 USHORT TMCylinders; /*54*/
211 USHORT TMHeads; /*55*/
212 USHORT TMSectorsPerTrk; /*56*/
213 USHORT TMCapacityLo; /*57*/
214 USHORT TMCapacityHi; /*58*/
215 USHORT RWMultCurrent; /*59*/
216 USHORT TMSectorCountLo; /*60*/
217 USHORT TMSectorCountHi; /*61*/
218 USHORT DmaModes; /*62*/
219 USHORT MultiDmaModes; /*63*/
220 USHORT Reserved64[5]; /*64*/
221 USHORT Reserved69[2]; /*69*/
222 USHORT Reserved71[4]; /*71*/
223 USHORT MaxQueueDepth; /*75*/
224 USHORT Reserved76[4]; /*76*/
225 USHORT MajorRevision; /*80*/
226 USHORT MinorRevision; /*81*/
227 USHORT SupportedFeatures82; /*82*/
228 USHORT SupportedFeatures83; /*83*/
229 USHORT SupportedFeatures84; /*84*/
230 USHORT EnabledFeatures85; /*85*/
231 USHORT EnabledFeatures86; /*86*/
232 USHORT EnabledFeatures87; /*87*/
233 USHORT UltraDmaModes; /*88*/
234 USHORT Reserved89[11]; /*89*/
235 USHORT Max48BitAddress[4]; /*100*/
236 USHORT Reserved104[151]; /*104*/
237 USHORT Checksum; /*255*/
238 } IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY;
239
240 /* XboxDiskPolledRead
241 *
242 * DESCRIPTION:
243 * Read a sector of data from the drive in a polled fashion.
244 *
245 * RUN LEVEL:
246 * PASSIVE_LEVEL
247 *
248 * ARGUMENTS:
249 * ULONG CommandPort Address of command port for drive
250 * ULONG ControlPort Address of control port for drive
251 * UCHAR PreComp Value to write to precomp register
252 * UCHAR SectorCnt Value to write to sectorCnt register
253 * UCHAR SectorNum Value to write to sectorNum register
254 * UCHAR CylinderLow Value to write to CylinderLow register
255 * UCHAR CylinderHigh Value to write to CylinderHigh register
256 * UCHAR DrvHead Value to write to Drive/Head register
257 * UCHAR Command Value to write to Command register
258 * PVOID Buffer Buffer for output data
259 *
260 * RETURNS:
261 * BOOLEAN: TRUE success, FALSE error
262 */
263
264 static BOOLEAN
265 XboxDiskPolledRead(ULONG CommandPort,
266 ULONG ControlPort,
267 UCHAR PreComp,
268 UCHAR SectorCnt,
269 UCHAR SectorNum,
270 UCHAR CylinderLow,
271 UCHAR CylinderHigh,
272 UCHAR DrvHead,
273 UCHAR Command,
274 PVOID Buffer)
275 {
276 ULONG SectorCount = 0;
277 ULONG RetryCount;
278 BOOLEAN Junk = FALSE;
279 UCHAR Status;
280
281 /* Wait for BUSY to clear */
282 for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
283 {
284 Status = IDEReadStatus(CommandPort);
285 if (!(Status & IDE_SR_BUSY))
286 {
287 break;
288 }
289 StallExecutionProcessor(10);
290 }
291 DbgPrint((DPRINT_DISK, "status=0x%x\n", Status));
292 DbgPrint((DPRINT_DISK, "waited %d usecs for busy to clear\n", RetryCount * 10));
293 if (RetryCount >= IDE_MAX_BUSY_RETRIES)
294 {
295 DbgPrint((DPRINT_DISK, "Drive is BUSY for too long\n"));
296 return FALSE;
297 }
298
299 /* Write Drive/Head to select drive */
300 IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
301 StallExecutionProcessor(500);
302
303 /* Disable interrupts */
304 IDEWriteDriveControl(ControlPort, IDE_DC_nIEN);
305 StallExecutionProcessor(500);
306
307 /* Issue command to drive */
308 if (DrvHead & IDE_DH_LBA)
309 {
310 DbgPrint((DPRINT_DISK, "READ:DRV=%d:LBA=1:BLK=%d:SC=0x%x:CM=0x%x\n",
311 DrvHead & IDE_DH_DRV1 ? 1 : 0,
312 ((DrvHead & 0x0f) << 24) + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum,
313 SectorCnt,
314 Command));
315 }
316 else
317 {
318 DbgPrint((DPRINT_DISK, "READ:DRV=%d:LBA=0:CH=0x%x:CL=0x%x:HD=0x%x:SN=0x%x:SC=0x%x:CM=0x%x\n",
319 DrvHead & IDE_DH_DRV1 ? 1 : 0,
320 CylinderHigh,
321 CylinderLow,
322 DrvHead & 0x0f,
323 SectorNum,
324 SectorCnt,
325 Command));
326 }
327
328 /* Setup command parameters */
329 IDEWritePrecomp(CommandPort, PreComp);
330 IDEWriteSectorCount(CommandPort, SectorCnt);
331 IDEWriteSectorNum(CommandPort, SectorNum);
332 IDEWriteCylinderHigh(CommandPort, CylinderHigh);
333 IDEWriteCylinderLow(CommandPort, CylinderLow);
334 IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
335
336 /* Issue the command */
337 IDEWriteCommand(CommandPort, Command);
338 StallExecutionProcessor(50);
339
340 /* wait for DRQ or error */
341 for (RetryCount = 0; RetryCount < IDE_MAX_POLL_RETRIES; RetryCount++)
342 {
343 Status = IDEReadStatus(CommandPort);
344 if (!(Status & IDE_SR_BUSY))
345 {
346 if (Status & IDE_SR_ERR)
347 {
348 IDEWriteDriveControl(ControlPort, 0);
349 StallExecutionProcessor(50);
350 IDEReadStatus(CommandPort);
351
352 return FALSE;
353 }
354
355 if (Status & IDE_SR_DRQ)
356 {
357 break;
358 }
359 else
360 {
361 IDEWriteDriveControl(ControlPort, 0);
362 StallExecutionProcessor(50);
363 IDEReadStatus(CommandPort);
364
365 return FALSE;
366 }
367 }
368 StallExecutionProcessor(10);
369 }
370
371 /* timed out */
372 if (RetryCount >= IDE_MAX_POLL_RETRIES)
373 {
374 IDEWriteDriveControl(ControlPort, 0);
375 StallExecutionProcessor(50);
376 IDEReadStatus(CommandPort);
377
378 return FALSE;
379 }
380
381 while (1)
382 {
383 /* Read data into buffer */
384 if (Junk == FALSE)
385 {
386 IDEReadBlock(CommandPort, Buffer, IDE_SECTOR_BUF_SZ);
387 Buffer = (PVOID)((ULONG_PTR)Buffer + IDE_SECTOR_BUF_SZ);
388 }
389 else
390 {
391 UCHAR JunkBuffer[IDE_SECTOR_BUF_SZ];
392 IDEReadBlock(CommandPort, JunkBuffer, IDE_SECTOR_BUF_SZ);
393 }
394 SectorCount++;
395
396 /* Check for error or more sectors to read */
397 for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
398 {
399 Status = IDEReadStatus(CommandPort);
400 if (!(Status & IDE_SR_BUSY))
401 {
402 if (Status & IDE_SR_ERR)
403 {
404 IDEWriteDriveControl(ControlPort, 0);
405 StallExecutionProcessor(50);
406 IDEReadStatus(CommandPort);
407
408 return FALSE;
409 }
410 if (Status & IDE_SR_DRQ)
411 {
412 if (SectorCount >= SectorCnt)
413 {
414 DbgPrint((DPRINT_DISK, "Buffer size exceeded!\n"));
415 Junk = TRUE;
416 }
417 break;
418 }
419 else
420 {
421 if (SectorCount > SectorCnt)
422 {
423 DbgPrint((DPRINT_DISK, "Read %lu sectors of junk!\n",
424 SectorCount - SectorCnt));
425 }
426 IDEWriteDriveControl(ControlPort, 0);
427 StallExecutionProcessor(50);
428 IDEReadStatus(CommandPort);
429
430 return TRUE;
431 }
432 }
433 }
434 }
435 }
436
437 BOOLEAN
438 XboxDiskReadLogicalSectors(ULONG DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
439 {
440 ULONG StartSector;
441 UCHAR Count;
442
443 if (DriveNumber < 0x80 || 2 <= (DriveNumber & 0x0f))
444 {
445 /* Xbox has only 1 IDE controller and no floppy */
446 DbgPrint((DPRINT_DISK, "Invalid drive number\n"));
447 return FALSE;
448 }
449
450 if (UINT64_C(0) != ((SectorNumber + SectorCount) & UINT64_C(0xfffffffff0000000)))
451 {
452 DbgPrint((DPRINT_DISK, "48bit LBA required but not implemented\n"));
453 return FALSE;
454 }
455
456 StartSector = (ULONG) SectorNumber;
457 while (0 < SectorCount)
458 {
459 Count = (SectorCount <= 255 ? SectorCount : 255);
460 if (! XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT,
461 XBOX_IDE_CONTROL_PORT,
462 0, Count,
463 StartSector & 0xff,
464 (StartSector >> 8) & 0xff,
465 (StartSector >> 16) & 0xff,
466 ((StartSector >> 24) & 0x0f) | IDE_DH_LBA |
467 (0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1),
468 IDE_CMD_READ,
469 Buffer))
470 {
471 return FALSE;
472 }
473 SectorCount -= Count;
474 Buffer = (PVOID) ((PCHAR) Buffer + Count * IDE_SECTOR_BUF_SZ);
475 }
476
477 return TRUE;
478 }
479
480 BOOLEAN
481 XboxDiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry)
482 {
483 UCHAR SectorData[IDE_SECTOR_BUF_SZ];
484
485 /* This is the Xbox, chances are that there is a Xbox-standard partitionless
486 * disk in it so let's check that first */
487
488 if (1 <= PartitionNumber && PartitionNumber <= sizeof(XboxPartitions) / sizeof(XboxPartitions[0]) &&
489 MachDiskReadLogicalSectors(DriveNumber, XBOX_SIGNATURE_SECTOR, 1, SectorData))
490 {
491 if (*((PULONG) SectorData) == XBOX_SIGNATURE)
492 {
493 memset(PartitionTableEntry, 0, sizeof(PARTITION_TABLE_ENTRY));
494 PartitionTableEntry->SystemIndicator = XboxPartitions[PartitionNumber - 1].SystemIndicator;
495 PartitionTableEntry->SectorCountBeforePartition = XboxPartitions[PartitionNumber - 1].SectorCountBeforePartition;
496 PartitionTableEntry->PartitionSectorCount = XboxPartitions[PartitionNumber - 1].PartitionSectorCount;
497 return TRUE;
498 }
499 }
500
501 /* No magic Xbox partitions. Maybe there's a MBR */
502 return DiskGetPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry);
503 }
504
505 BOOLEAN
506 XboxDiskGetDriveGeometry(ULONG DriveNumber, PGEOMETRY Geometry)
507 {
508 IDE_DRIVE_IDENTIFY DrvParms;
509 ULONG i;
510 BOOLEAN Atapi;
511
512 Atapi = FALSE; /* FIXME */
513 /* Get the Drive Identify block from drive or die */
514 if (! XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT,
515 XBOX_IDE_CONTROL_PORT,
516 0,
517 1,
518 0,
519 0,
520 0,
521 (0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1),
522 (Atapi ? IDE_CMD_IDENT_ATAPI_DRV : IDE_CMD_IDENT_ATA_DRV),
523 (PUCHAR) &DrvParms))
524 {
525 DbgPrint((DPRINT_DISK, "XboxDiskPolledRead() failed\n"));
526 return FALSE;
527 }
528
529 Geometry->Cylinders = DrvParms.LogicalCyls;
530 Geometry->Heads = DrvParms.LogicalHeads;
531 Geometry->Sectors = DrvParms.SectorsPerTrack;
532
533 if (! Atapi && 0 != (DrvParms.Capabilities & IDE_DRID_LBA_SUPPORTED))
534 {
535 /* LBA ATA drives always have a sector size of 512 */
536 Geometry->BytesPerSector = 512;
537 }
538 else
539 {
540 DbgPrint((DPRINT_DISK, "BytesPerSector %d\n", DrvParms.BytesPerSector));
541 if (DrvParms.BytesPerSector == 0)
542 {
543 Geometry->BytesPerSector = 512;
544 }
545 else
546 {
547 for (i = 1 << 15; i; i /= 2)
548 {
549 if (0 != (DrvParms.BytesPerSector & i))
550 {
551 Geometry->BytesPerSector = i;
552 break;
553 }
554 }
555 }
556 }
557 DbgPrint((DPRINT_DISK, "Cylinders %d\n", Geometry->Cylinders));
558 DbgPrint((DPRINT_DISK, "Heads %d\n", Geometry->Heads));
559 DbgPrint((DPRINT_DISK, "Sectors %d\n", Geometry->Sectors));
560 DbgPrint((DPRINT_DISK, "BytesPerSector %d\n", Geometry->BytesPerSector));
561
562 return TRUE;
563 }
564
565 ULONG
566 XboxDiskGetCacheableBlockCount(ULONG DriveNumber)
567 {
568 /* 64 seems a nice number, it is used by the machpc code for LBA devices */
569 return 64;
570 }
571
572 /* EOF */