summaryrefslogtreecommitdiff
path: root/kernel/drivers/ata.c
blob: 9117d85a034bb73e93c775aa1a3851530d42ac1a (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
72
73
74
75
76
77
78
79
80
81
82
83
// taken from https://wiki.osdev.org/PCI#Class_Codes
#define CLASS_MASS_STORAGE_CONTROLLER 0x1

#define SUBCLASS_SCSI_BUS_CONTROLLER 0x0
#define SUBCLASS_IDE_CONTROLLER 0x1
#define SUBCLASS_FLOPPY_DISK_CONTROLLER 0x2
#define SUBCLASS_IPI_BUS_CONTROLLER 0x3
#define SUBCLASS_RAID_CONTROLLER 0x4
#define SUBCLASS_ATA_CONTROLLER 0x5
#define SUBCLASS_SERIAL_ATA_CONTROLLER 0x6
#define SUBCLASS_SERIAL_ATTACHED_SCSI_CONTROLLER 0x7
#define SUBCLASS_NON_VOLATILE_MEMORY_CONTROLLER 0x8
#define SUBCLASS_OTHER 0x80

// from https://wiki.osdev.org/PCI_IDE_Controller#Detecting_a_PCI_IDE_Controller
#define IDE_PROG_IF_PRIMARY_CHANNEL_IS_PCI_NATIVE_FLAG 0x1
#define IDE_PROG_IF_PRIMARY_CHANNEL_CAN_SWITCH_TO_AND_FROM_PCI_NATIVE_FLAG 0x2
#define IDE_PROG_IF_SECONDARY_CHANNEL_IS_PCI_NATIVE_FLAG 0x3
#define IDE_PROG_IF_SECONDARY_CHANNEL_CAN_SWITCH_TO_AND_FROM_PCI_NATIVE_FLAG 0x4
#define IDE_PROG_IF_DMA_SUPPORT_FLAG 0x7

// ATA statuses, read off of the command/status port
// clang-format off
#define ATA_SR_BUSY                 0x80
#define ATA_SR_DRIVEREADY           0x40
#define ATA_SR_DRIVEWRITEFAULT      0x20
#define ATA_SR_DRIVESEEKCOMPLETE    0x10
#define ATA_SR_DRIVEREQUESTREADY    0x08
#define ATA_SR_CORRECTEDATA         0x04
#define ATA_SR_INDEX                0x02
#define ATA_SR_ERROR                0x01
// clang-format on

// ATA errors, ready off of the features/error port
// clang-format off
#define ATA_ER_BADBLOCK             0x80
#define ATA_ER_UNCORRECTABLE        0x40
#define ATA_ER_MEDIACHANGED         0x20
#define ATA_ER_IDMARKNOTFOUND       0x10
#define ATA_ER_MEDIACHANGEREQUEST   0x08
#define ATA_ER_COMMANDABORTED       0x04
#define ATA_ER_TRACK0NOTFOUND       0x02
#define ATA_ER_NOADDRESSMARK        0x01
// clang-format on

// ATA commands
// clang-format off
#define ATA_CMD_READ_PIO          0x20
#define ATA_CMD_READ_PIO_EXT      0x24
#define ATA_CMD_READ_DMA          0xC8
#define ATA_CMD_READ_DMA_EXT      0x25
#define ATA_CMD_WRITE_PIO         0x30
#define ATA_CMD_WRITE_PIO_EXT     0x34
#define ATA_CMD_WRITE_DMA         0xCA
#define ATA_CMD_WRITE_DMA_EXT     0x35
#define ATA_CMD_CACHE_FLUSH       0xE7
#define ATA_CMD_CACHE_FLUSH_EXT   0xEA
#define ATA_CMD_PACKET            0xA0
#define ATA_CMD_IDENTIFY_PACKET   0xA1
#define ATA_CMD_IDENTIFY          0xEC
// clang-format on

#include <comus/drivers/ata.h>
#include <comus/drivers/pci.h>
#include <lib.h>

bool ata_find_primary_drive(struct pci_device *out)
{
	if (!pci_findby_class(out, CLASS_MASS_STORAGE_CONTROLLER,
						  SUBCLASS_IDE_CONTROLLER, NULL)) {
		return false;
	}

	const uint8_t prog_if = pci_rcfg_b(*out, PCI_PROG_IF_B);
	const uint8_t header_type = pci_rcfg_b(*out, PCI_HEADER_TYPE_B);

	if (header_type != 0x0) {
		TRACE("Wrong header type for IDE_CONTROLLER device, not reading BARs");
		return false;
	}

	return true;
}