Rev 4507 | Rev 4530 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4507 | Rev 4529 | ||
---|---|---|---|
Line 48... | Line 48... | ||
48 | #include <as.h> |
48 | #include <as.h> |
49 | #include <futex.h> |
49 | #include <futex.h> |
50 | #include <devmap.h> |
50 | #include <devmap.h> |
51 | #include <sys/types.h> |
51 | #include <sys/types.h> |
52 | #include <errno.h> |
52 | #include <errno.h> |
- | 53 | #include <bool.h> |
|
53 | 54 | ||
54 | #define NAME "ata_bd" |
55 | #define NAME "ata_bd" |
55 | 56 | ||
56 | enum { |
57 | enum { |
57 | CTL_READ_START = 0, |
58 | CTL_READ_START = 0, |
Line 131... | Line 132... | ||
131 | ER_ABRT = 0x04, /**< Aborted Command */ |
132 | ER_ABRT = 0x04, /**< Aborted Command */ |
132 | ER_TK0NF = 0x02, /**< Track 0 Not Found */ |
133 | ER_TK0NF = 0x02, /**< Track 0 Not Found */ |
133 | ER_AMNF = 0x01 /**< Address Mark Not Found */ |
134 | ER_AMNF = 0x01 /**< Address Mark Not Found */ |
134 | }; |
135 | }; |
135 | 136 | ||
- | 137 | typedef struct { |
|
- | 138 | bool present; |
|
- | 139 | unsigned heads; |
|
- | 140 | unsigned cylinders; |
|
- | 141 | unsigned sectors; |
|
- | 142 | uint64_t blocks; |
|
- | 143 | } disk_t; |
|
- | 144 | ||
136 | static const size_t block_size = 512; |
145 | static const size_t block_size = 512; |
137 | static size_t comm_size; |
146 | static size_t comm_size; |
138 | 147 | ||
139 | static uintptr_t cmd_physical = 0x1f0; |
148 | static uintptr_t cmd_physical = 0x1f0; |
140 | static uintptr_t ctl_physical = 0x170; |
149 | static uintptr_t ctl_physical = 0x170; |
Line 143... | Line 152... | ||
143 | 152 | ||
144 | static dev_handle_t dev_handle[MAX_DISKS]; |
153 | static dev_handle_t dev_handle[MAX_DISKS]; |
145 | 154 | ||
146 | static atomic_t dev_futex = FUTEX_INITIALIZER; |
155 | static atomic_t dev_futex = FUTEX_INITIALIZER; |
147 | 156 | ||
148 | static unsigned heads, cylinders, sectors; |
- | |
149 | static uint64_t disk_blocks; |
157 | static disk_t disk[2]; |
150 | 158 | ||
151 | static int ata_bd_init(void); |
159 | static int ata_bd_init(void); |
152 | static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall); |
160 | static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall); |
153 | static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, off_t size, |
161 | static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, off_t size, |
154 | void *buf); |
162 | void *buf); |
155 | static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt, |
163 | static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt, |
156 | void *buf); |
164 | void *buf); |
- | 165 | static int drive_identify(int drive_id, disk_t *d); |
|
157 | 166 | ||
158 | int main(int argc, char **argv) |
167 | int main(int argc, char **argv) |
159 | { |
168 | { |
160 | uint8_t status; |
169 | uint8_t status; |
- | 170 | char name[16]; |
|
161 | uint16_t data; |
171 | int i, rc; |
162 | int i; |
172 | int n_disks; |
163 | 173 | ||
164 | printf(NAME ": ATA disk driver\n"); |
174 | printf(NAME ": ATA disk driver\n"); |
165 | 175 | ||
166 | printf("cmd_physical = 0x%x\n", cmd_physical); |
176 | printf("cmd_physical = 0x%x\n", cmd_physical); |
167 | printf("ctl_physical = 0x%x\n", ctl_physical); |
177 | printf("ctl_physical = 0x%x\n", ctl_physical); |
Line 185... | Line 195... | ||
185 | } while ((status & SR_BSY) != 0); |
195 | } while ((status & SR_BSY) != 0); |
186 | printf("Done\n"); |
196 | printf("Done\n"); |
187 | 197 | ||
188 | printf("Status = 0x%x\n", pio_read_8(&cmd->status)); |
198 | printf("Status = 0x%x\n", pio_read_8(&cmd->status)); |
189 | 199 | ||
- | 200 | (void) drive_identify(0, &disk[0]); |
|
- | 201 | (void) drive_identify(1, &disk[1]); |
|
- | 202 | ||
- | 203 | n_disks = 0; |
|
- | 204 | ||
- | 205 | for (i = 0; i < MAX_DISKS; i++) { |
|
- | 206 | /* Skip unattached drives. */ |
|
- | 207 | if (disk[i].present == false) |
|
- | 208 | continue; |
|
- | 209 | ||
- | 210 | snprintf(name, 16, "disk%d", i); |
|
- | 211 | rc = devmap_device_register(name, &dev_handle[i]); |
|
- | 212 | if (rc != EOK) { |
|
- | 213 | devmap_hangup_phone(DEVMAP_DRIVER); |
|
- | 214 | printf(NAME ": Unable to register device %s.\n", |
|
- | 215 | name); |
|
- | 216 | return rc; |
|
- | 217 | } |
|
- | 218 | ++n_disks; |
|
- | 219 | } |
|
- | 220 | ||
- | 221 | if (n_disks == 0) { |
|
- | 222 | printf("No disks detected.\n"); |
|
- | 223 | return -1; |
|
- | 224 | } |
|
- | 225 | ||
- | 226 | printf(NAME ": Accepting connections\n"); |
|
- | 227 | async_manager(); |
|
- | 228 | ||
- | 229 | /* Not reached */ |
|
- | 230 | return 0; |
|
- | 231 | } |
|
- | 232 | ||
- | 233 | static int drive_identify(int disk_id, disk_t *d) |
|
- | 234 | { |
|
- | 235 | uint16_t data; |
|
- | 236 | uint8_t status; |
|
- | 237 | int i; |
|
- | 238 | ||
190 | printf("Issue drive_identify command\n"); |
239 | printf("Identify drive %d\n", disk_id); |
191 | pio_write_8(&cmd->drive_head, 0x00); |
240 | pio_write_8(&cmd->drive_head, ((disk_id != 0) ? DHR_DRV : 0)); |
192 | async_usleep(100); |
241 | async_usleep(100); |
193 | pio_write_8(&cmd->command, 0xEC); |
242 | pio_write_8(&cmd->command, 0xEC); |
194 | 243 | ||
- | 244 | status = pio_read_8(&cmd->status); |
|
195 | printf("Status = 0x%x\n", pio_read_8(&cmd->status)); |
245 | printf("Status = 0x%x\n", status); |
- | 246 | ||
- | 247 | d->present = false; |
|
- | 248 | ||
- | 249 | /* |
|
- | 250 | * Detect if drive is present. This is Qemu only! Need to |
|
- | 251 | * do the right thing to work with real drives. |
|
- | 252 | */ |
|
- | 253 | if ((status & SR_DRDY) == 0) { |
|
- | 254 | printf("None attached.\n"); |
|
- | 255 | return ENOENT; |
|
- | 256 | } |
|
196 | 257 | ||
197 | for (i = 0; i < 256; i++) { |
258 | for (i = 0; i < 256; i++) { |
198 | do { |
259 | do { |
199 | status = pio_read_8(&cmd->status); |
260 | status = pio_read_8(&cmd->status); |
200 | } while ((status & SR_DRDY) == 0); |
261 | } while ((status & SR_DRDY) == 0); |
201 | 262 | ||
202 | data = pio_read_16(&cmd->data_port); |
263 | data = pio_read_16(&cmd->data_port); |
203 | 264 | ||
204 | switch (i) { |
265 | switch (i) { |
205 | case 1: cylinders = data; break; |
266 | case 1: d->cylinders = data; break; |
206 | case 3: heads = data; break; |
267 | case 3: d->heads = data; break; |
207 | case 6: sectors = data; break; |
268 | case 6: d->sectors = data; break; |
208 | } |
269 | } |
209 | } |
270 | } |
210 | 271 | ||
211 | printf("\n\nStatus = 0x%x\n", pio_read_8(&cmd->status)); |
272 | printf("\n\nStatus = 0x%x\n", pio_read_8(&cmd->status)); |
212 | 273 | ||
- | 274 | d->blocks = d->cylinders * d->heads * d->sectors; |
|
- | 275 | ||
213 | printf("Geometry: %u cylinders, %u heads, %u sectors\n", |
276 | printf("Geometry: %u cylinders, %u heads, %u sectors\n", |
214 | cylinders, heads, sectors); |
277 | d->cylinders, d->heads, d->sectors); |
215 | disk_blocks = cylinders * heads * sectors; |
- | |
216 | 278 | ||
217 | printf(NAME ": Accepting connections\n"); |
- | |
218 | async_manager(); |
279 | d->present = true; |
219 | 280 | ||
220 | /* Not reached */ |
- | |
221 | return 0; |
281 | return EOK; |
222 | } |
282 | } |
223 | 283 | ||
224 | static int ata_bd_init(void) |
284 | static int ata_bd_init(void) |
225 | { |
285 | { |
226 | void *vaddr; |
286 | void *vaddr; |
227 | int rc, i; |
287 | int rc; |
228 | char name[16]; |
- | |
229 | 288 | ||
230 | rc = devmap_driver_register(NAME, ata_bd_connection); |
289 | rc = devmap_driver_register(NAME, ata_bd_connection); |
231 | if (rc < 0) { |
290 | if (rc < 0) { |
232 | printf(NAME ": Unable to register driver.\n"); |
291 | printf(NAME ": Unable to register driver.\n"); |
233 | return rc; |
292 | return rc; |
Line 247... | Line 306... | ||
247 | return rc; |
306 | return rc; |
248 | } |
307 | } |
249 | 308 | ||
250 | ctl = vaddr; |
309 | ctl = vaddr; |
251 | 310 | ||
252 | for (i = 0; i < MAX_DISKS; i++) { |
- | |
253 | snprintf(name, 16, "disk%d", i); |
- | |
254 | rc = devmap_device_register(name, &dev_handle[i]); |
- | |
255 | if (rc != EOK) { |
- | |
256 | devmap_hangup_phone(DEVMAP_DRIVER); |
- | |
257 | printf(NAME ": Unable to register device %s.\n", |
- | |
258 | name); |
- | |
259 | return rc; |
- | |
260 | } |
- | |
261 | } |
- | |
262 | 311 | ||
263 | return EOK; |
312 | return EOK; |
264 | } |
313 | } |
265 | 314 | ||
266 | static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall) |
315 | static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall) |
Line 283... | Line 332... | ||
283 | disk_id = -1; |
332 | disk_id = -1; |
284 | for (i = 0; i < MAX_DISKS; i++) |
333 | for (i = 0; i < MAX_DISKS; i++) |
285 | if (dev_handle[i] == dh) |
334 | if (dev_handle[i] == dh) |
286 | disk_id = i; |
335 | disk_id = i; |
287 | 336 | ||
288 | if (disk_id < 0) { |
337 | if (disk_id < 0 || disk[disk_id].present == false) { |
289 | ipc_answer_0(iid, EINVAL); |
338 | ipc_answer_0(iid, EINVAL); |
290 | return; |
339 | return; |
291 | } |
340 | } |
292 | 341 | ||
293 | /* Answer the IPC_M_CONNECT_ME_TO call. */ |
342 | /* Answer the IPC_M_CONNECT_ME_TO call. */ |
Line 372... | Line 421... | ||
372 | uint16_t data; |
421 | uint16_t data; |
373 | uint8_t status; |
422 | uint8_t status; |
374 | uint64_t c, h, s; |
423 | uint64_t c, h, s; |
375 | uint64_t idx; |
424 | uint64_t idx; |
376 | uint8_t drv_head; |
425 | uint8_t drv_head; |
- | 426 | disk_t *d; |
|
- | 427 | ||
- | 428 | d = &disk[disk_id]; |
|
377 | 429 | ||
378 | /* Check device bounds. */ |
430 | /* Check device bounds. */ |
379 | if (blk_idx >= disk_blocks) |
431 | if (blk_idx >= d->blocks) |
380 | return EINVAL; |
432 | return EINVAL; |
381 | 433 | ||
382 | /* Compute CHS. */ |
434 | /* Compute CHS. */ |
383 | c = blk_idx / (heads * sectors); |
435 | c = blk_idx / (d->heads * d->sectors); |
384 | idx = blk_idx % (heads * sectors); |
436 | idx = blk_idx % (d->heads * d->sectors); |
385 | 437 | ||
386 | h = idx / sectors; |
438 | h = idx / d->sectors; |
387 | s = 1 + (idx % sectors); |
439 | s = 1 + (idx % d->sectors); |
388 | 440 | ||
389 | /* New value for Drive/Head register */ |
441 | /* New value for Drive/Head register */ |
390 | drv_head = |
442 | drv_head = |
391 | ((disk_id != 0) ? DHR_DRV : 0) | |
443 | ((disk_id != 0) ? DHR_DRV : 0) | |
392 | (h & 0x0f); |
444 | (h & 0x0f); |