3 * Copyright (C) 2012 secunet Security Networks AG
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <libpayload.h>
31 #include <storage/ahci.h>
32 #include <storage/nvme.h>
33 #include <storage/storage.h>
35 static storage_dev_t
**devices
= NULL
;
36 static size_t devices_length
= 0;
37 static size_t dev_count
= 0;
39 int storage_attach_device(storage_dev_t
*const dev
)
41 if (dev_count
== devices_length
) {
42 const size_t new_len
=
43 (0 == devices_length
) ? 4 : devices_length
<< 1;
44 storage_dev_t
**const new_devices
=
45 realloc(devices
, new_len
* sizeof(storage_dev_t
*));
48 devices
= new_devices
;
49 memset(devices
+ devices_length
, '\0',
50 (new_len
- devices_length
) * sizeof(storage_dev_t
*));
51 devices_length
= new_len
;
53 devices
[dev_count
++] = dev
;
58 int storage_device_count(void)
64 * Probe for drive with given number
66 * Looks for a drive with number dev_num and polls for a medium
67 * in the drive if appropriate.
69 * @dev_num device number counted from 0
71 storage_poll_t
storage_probe(const size_t dev_num
)
73 if (dev_num
>= dev_count
)
74 return POLL_NO_DEVICE
;
75 else if (devices
[dev_num
]->poll
)
76 return devices
[dev_num
]->poll(devices
[dev_num
]);
78 return POLL_MEDIUM_PRESENT
;
82 * Read 512-byte blocks
84 * Reads count blocks of 512 bytes from block start of drive dev_num
87 * @dev_num device number counted from 0
88 * @start number of first block to read from
89 * @count number of blocks to read
90 * @buf buffer where the read data should be written
92 ssize_t
storage_read_blocks512(const size_t dev_num
,
93 const lba_t start
, const size_t count
,
94 unsigned char *const buf
)
96 if ((dev_num
< dev_count
) && devices
[dev_num
]->read_blocks512
)
97 return devices
[dev_num
]->read_blocks512(
98 devices
[dev_num
], start
, count
, buf
);
104 * Initializes storage controllers
106 * This function should be called once at startup to bring up supported
107 * storage controllers.
109 void storage_initialize(void)
113 for (dev
= lib_sysinfo
.pacc
.devices
; dev
; dev
= dev
->next
) {
114 switch (dev
->device_class
) {
115 #if CONFIG(LP_STORAGE_AHCI)
116 case PCI_CLASS_STORAGE_AHCI
:
117 ahci_initialize(dev
);
120 #if CONFIG(LP_STORAGE_NVME)
121 case PCI_CLASS_STORAGE_NVME
:
122 nvme_initialize(dev
);