aboutsummaryrefslogtreecommitdiffstats
path: root/src/ata.h
blob: 074ed555770ea686afb6c890713d4f1caaffbf58 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// Low level ATA disk definitions
//
// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2002  MandrakeSoft S.A.
//
// This file may be distributed under the terms of the GNU GPLv3 license.

#ifndef __ATA_H
#define __ATA_H

#include "types.h" // u16
#include "atabits.h" // ATA_CB_DH_DEV1

struct ata_pio_command {
    void *far_buffer;
    u8 biosid;

    u8 feature;
    u8 sector_count;
    u8 lba_low;
    u8 lba_mid;
    u8 lba_high;
    u8 device;
    u8 command;

    u8 sector_count2;
    u8 lba_low2;
    u8 lba_mid2;
    u8 lba_high2;
};

// Function definitions
void ata_reset(u16 device);
int ata_transfer(struct ata_pio_command *cmd);
int ata_cmd_packet(u16 device, u8 *cmdbuf, u8 cmdlen
                   , u32 length, void *far_buffer);
int cdrom_read(u16 device, u32 lba, u32 count, void *far_buffer);
int cdrom_read_512(u16 device, u32 lba, u32 count, void *far_buffer);
void ata_detect();

static inline int
ata_cmd_data(u16 biosid, u16 command, u32 lba, u16 count, void *far_buffer)
{
    u8 slave   = biosid % 2;

    struct ata_pio_command cmd;
    cmd.far_buffer = far_buffer;
    cmd.biosid = biosid;

    if (count >= (1<<8) || lba + count >= (1<<28)) {
        cmd.sector_count2 = count >> 8;
        cmd.lba_low2 = lba >> 24;
        cmd.lba_mid2 = 0;
        cmd.lba_high2 = 0;

        command |= 0x04;
        lba &= 0xffffff;
    }

    cmd.feature = 0;
    cmd.sector_count = count;
    cmd.lba_low = lba;
    cmd.lba_mid = lba >> 8;
    cmd.lba_high = lba >> 16;
    cmd.device = ((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0)
                  | ((lba >> 24) & 0xf) | ATA_CB_DH_LBA);
    cmd.command = command;
    return ata_transfer(&cmd);
}

#endif /* __ATA_H */