Reorganize ata code; reduce stack usage.
[people/mcb30/legacybios.git] / src / ata.h
1 // Low level ATA disk definitions
2 //
3 // Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2002  MandrakeSoft S.A.
5 //
6 // This file may be distributed under the terms of the GNU GPLv3 license.
7
8 #ifndef __ATA_H
9 #define __ATA_H
10
11 #include "types.h" // u16
12 #include "atabits.h"
13
14 struct ata_pio_command {
15     u16 segment;
16     u16 offset;
17     u8 biosid;
18
19     u8 feature;
20     u8 sector_count;
21     u8 lba_low;
22     u8 lba_mid;
23     u8 lba_high;
24     u8 device;
25     u8 command;
26
27     u8 sector_count2;
28     u8 lba_low2;
29     u8 lba_mid2;
30     u8 lba_high2;
31 };
32
33 // Function definitions
34 void ata_reset(u16 device);
35 int ata_transfer(struct ata_pio_command *cmd);
36 int ata_cmd_packet(u16 device, u8 *cmdbuf, u8 cmdlen
37                    , u16 header, u32 length, u16 bufseg, u16 bufoff);
38 int cdrom_read(u16 device, u32 lba, u32 count
39                , u16 segment, u16 offset, u16 skip);
40 void ata_detect();
41
42 static inline int
43 ata_cmd_data(u16 biosid, u16 command, u32 lba, u16 count
44              , u16 segment, u16 offset)
45 {
46     u8 slave   = biosid % 2;
47
48     struct ata_pio_command cmd;
49     cmd.biosid = biosid;
50     cmd.segment = segment;
51     cmd.offset = offset;
52
53     if (count >= (1<<8) || lba + count >= (1<<28)) {
54         cmd.sector_count2 = count >> 8;
55         cmd.lba_low2 = lba >> 24;
56         cmd.lba_mid2 = 0;
57         cmd.lba_high2 = 0;
58
59         command |= 0x04;
60         lba &= 0xffffff;
61     }
62
63     cmd.feature = 0;
64     cmd.sector_count = count;
65     cmd.lba_low = lba;
66     cmd.lba_mid = lba >> 8;
67     cmd.lba_high = lba >> 16;
68     cmd.device = ((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0)
69                   | ((lba >> 24) & 0xf) | ATA_CB_DH_LBA);
70     cmd.command = command;
71     return ata_transfer(&cmd);
72 }
73
74 static inline int
75 ata_cmd_data_chs(u16 biosid, u16 command, u16 cyl, u16 head, u16 sect, u16 count
76                  , u16 segment, u16 offset)
77 {
78     u8 slave   = biosid % 2;
79
80     struct ata_pio_command cmd;
81     cmd.biosid = biosid;
82     cmd.segment = segment;
83     cmd.offset = offset;
84
85     cmd.sector_count = count & 0xff;
86     cmd.feature = 0;
87     cmd.lba_low = sect;
88     cmd.lba_mid = cyl;
89     cmd.lba_high = cyl >> 8;
90     cmd.device = (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (head & 0xff);
91     cmd.command = command;
92     return ata_transfer(&cmd);
93 }
94
95 #endif /* __ATA_H */