Changes in / [42cfd91:330965c] in mainline
- Location:
- uspace/srv/bd/ata_bd
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/bd/ata_bd/ata_bd.c
r42cfd91 r330965c 60 60 #define NAME "ata_bd" 61 61 62 /** Physical block size. Should be always 512. */ 62 63 static const size_t block_size = 512; 64 65 /** Size of the communication area. */ 63 66 static size_t comm_size; 64 67 68 /** I/O base address of the command registers. */ 65 69 static uintptr_t cmd_physical = 0x1f0; 70 /** I/O base address of the control registers. */ 66 71 static uintptr_t ctl_physical = 0x170; 72 67 73 static ata_cmd_t *cmd; 68 74 static ata_ctl_t *ctl; … … 80 86 const void *buf); 81 87 static int drive_identify(int drive_id, disk_t *d); 88 static int wait_status(unsigned set, unsigned n_reset, uint8_t *pstatus, 89 unsigned timeout); 82 90 83 91 int main(int argc, char **argv) 84 92 { 85 uint8_t status;86 93 char name[16]; 87 94 int i, rc; … … 95 102 return -1; 96 103 97 (void) drive_identify(0, &disk[0]); 98 (void) drive_identify(1, &disk[1]); 104 for (i = 0; i < MAX_DISKS; i++) { 105 printf("Identify drive %d... ", i); 106 fflush(stdout); 107 108 rc = drive_identify(i, &disk[i]); 109 110 if (rc == EOK) { 111 printf("%u cylinders, %u heads, %u sectors\n", 112 disk[i].cylinders, disk[i].heads, disk[i].sectors); 113 } else { 114 printf("Not found.\n"); 115 } 116 } 99 117 100 118 n_disks = 0; … … 129 147 } 130 148 131 static int drive_identify(int disk_id, disk_t *d) 132 { 133 uint16_t data; 134 uint8_t status; 135 uint8_t drv_head; 136 size_t i; 137 138 printf("Identify drive %d... ", disk_id); 139 fflush(stdout); 140 141 drv_head = ((disk_id != 0) ? DHR_DRV : 0); 142 d->present = false; 143 144 do { 145 status = pio_read_8(&cmd->status); 146 } while ((status & SR_BSY) != 0); 147 148 pio_write_8(&cmd->drive_head, drv_head); 149 150 /* 151 * Detect if drive is present. This is Qemu only! Need to 152 * do the right thing to work with real drives. 153 */ 154 do { 155 status = pio_read_8(&cmd->status); 156 } while ((status & SR_BSY) != 0); 157 158 if ((status & SR_DRDY) == 0) { 159 printf("None attached.\n"); 160 return ENOENT; 161 } 162 /***/ 163 164 do { 165 status = pio_read_8(&cmd->status); 166 } while ((status & SR_BSY) != 0 || (status & SR_DRDY) == 0); 167 168 pio_write_8(&cmd->command, CMD_IDENTIFY_DRIVE); 169 170 do { 171 status = pio_read_8(&cmd->status); 172 } while ((status & SR_BSY) != 0); 173 174 /* Read data from the disk buffer. */ 175 176 if ((status & SR_DRQ) != 0) { 177 // for (i = 0; i < block_size / 2; i++) { 178 // data = pio_read_16(&cmd->data_port); 179 // ((uint16_t *) buf)[i] = data; 180 // } 181 182 for (i = 0; i < block_size / 2; i++) { 183 data = pio_read_16(&cmd->data_port); 184 185 switch (i) { 186 case 1: d->cylinders = data; break; 187 case 3: d->heads = data; break; 188 case 6: d->sectors = data; break; 189 } 190 } 191 } 192 193 if ((status & SR_ERR) != 0) 194 return EIO; 195 196 d->blocks = d->cylinders * d->heads * d->sectors; 197 198 printf("Geometry: %u cylinders, %u heads, %u sectors\n", 199 d->cylinders, d->heads, d->sectors); 200 201 d->present = true; 202 fibril_mutex_initialize(&d->lock); 203 204 return EOK; 205 } 206 149 150 /** Register driver and enable device I/O. */ 207 151 static int ata_bd_init(void) 208 152 { … … 236 180 } 237 181 182 /** Block device connection handler */ 238 183 static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall) 239 184 { … … 306 251 } 307 252 253 /** Transfer a logical block from/to the device. 254 * 255 * @param disk_id Device index (0 or 1) 256 * @param method @c BD_READ_BLOCK or @c BD_WRITE_BLOCK 257 * @param blk_idx Index of the first block. 258 * @param size Size of the logical block. 259 * @param buf Data buffer. 260 * 261 * @return EOK on success, EIO on error. 262 */ 308 263 static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t blk_idx, size_t size, 309 264 void *buf) … … 337 292 } 338 293 339 294 /** Issue IDENTIFY command. 295 * 296 * This is used to detect whether an ATA device is present and if so, 297 * to determine its parameters. The parameters are written to @a d. 298 * 299 * @param disk_id Device ID, 0 or 1. 300 * @param d Device structure to store parameters in. 301 */ 302 static int drive_identify(int disk_id, disk_t *d) 303 { 304 uint16_t data; 305 uint8_t status; 306 uint8_t drv_head; 307 size_t i; 308 309 drv_head = ((disk_id != 0) ? DHR_DRV : 0); 310 d->present = false; 311 312 if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) 313 return EIO; 314 315 pio_write_8(&cmd->drive_head, drv_head); 316 317 /* 318 * This is where we would most likely expect a non-existing device to 319 * show up by not setting SR_DRDY. 320 */ 321 if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) 322 return EIO; 323 324 pio_write_8(&cmd->command, CMD_IDENTIFY_DRIVE); 325 326 if (wait_status(0, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK) 327 return EIO; 328 329 /* Read data from the disk buffer. */ 330 331 if ((status & SR_DRQ) != 0) { 332 // for (i = 0; i < block_size / 2; i++) { 333 // data = pio_read_16(&cmd->data_port); 334 // ((uint16_t *) buf)[i] = data; 335 // } 336 337 for (i = 0; i < block_size / 2; i++) { 338 data = pio_read_16(&cmd->data_port); 339 340 switch (i) { 341 case 1: d->cylinders = data; break; 342 case 3: d->heads = data; break; 343 case 6: d->sectors = data; break; 344 } 345 } 346 } 347 348 if ((status & SR_ERR) != 0) 349 return EIO; 350 351 d->blocks = d->cylinders * d->heads * d->sectors; 352 353 d->present = true; 354 fibril_mutex_initialize(&d->lock); 355 356 return EOK; 357 } 358 359 /** Read a physical from the device. 360 * 361 * @param disk_id Device index (0 or 1) 362 * @param blk_idx Index of the first block. 363 * @param blk_cnt Number of blocks to transfer. 364 * @param buf Buffer for holding the data. 365 * 366 * @return EOK on success, EIO on error. 367 */ 340 368 static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt, 341 369 void *buf) … … 371 399 /* Program a Read Sectors operation. */ 372 400 373 do { 374 status = pio_read_8(&cmd->status); 375 } while ((status & SR_BSY) != 0); 401 if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) { 402 fibril_mutex_unlock(&d->lock); 403 return EIO; 404 } 376 405 377 406 pio_write_8(&cmd->drive_head, drv_head); 378 407 379 do { 380 status = pio_read_8(&cmd->status); 381 } while ((status & SR_BSY) != 0 || (status & SR_DRDY) == 0); 408 if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) { 409 fibril_mutex_unlock(&d->lock); 410 return EIO; 411 } 382 412 383 413 pio_write_8(&cmd->sector_count, 1); … … 388 418 pio_write_8(&cmd->command, CMD_READ_SECTORS); 389 419 390 do { 391 status = pio_read_8(&cmd->status); 392 } while ((status & SR_BSY) != 0); 393 394 /* Read data from the disk buffer. */ 420 if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) { 421 fibril_mutex_unlock(&d->lock); 422 return EIO; 423 } 395 424 396 425 if ((status & SR_DRQ) != 0) { 426 /* Read data from the device buffer. */ 427 397 428 for (i = 0; i < block_size / 2; i++) { 398 429 data = pio_read_16(&cmd->data_port); … … 408 439 } 409 440 441 /** Write a physical block to the device. 442 * 443 * @param disk_id Device index (0 or 1) 444 * @param blk_idx Index of the first block. 445 * @param blk_cnt Number of blocks to transfer. 446 * @param buf Buffer holding the data to write. 447 * 448 * @return EOK on success, EIO on error. 449 */ 410 450 static int ata_bd_write_block(int disk_id, uint64_t blk_idx, size_t blk_cnt, 411 451 const void *buf) … … 438 478 fibril_mutex_lock(&d->lock); 439 479 440 /* Program a Read Sectors operation. */ 441 442 do { 443 status = pio_read_8(&cmd->status); 444 } while ((status & SR_BSY) != 0); 445 480 /* Program a Write Sectors operation. */ 481 482 if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) { 483 fibril_mutex_unlock(&d->lock); 484 return EIO; 485 } 486 446 487 pio_write_8(&cmd->drive_head, drv_head); 447 488 448 do { 449 status = pio_read_8(&cmd->status); 450 } while ((status & SR_BSY) != 0 || (status & SR_DRDY) == 0); 489 if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) { 490 fibril_mutex_unlock(&d->lock); 491 return EIO; 492 } 451 493 452 494 pio_write_8(&cmd->sector_count, 1); … … 457 499 pio_write_8(&cmd->command, CMD_WRITE_SECTORS); 458 500 459 do { 460 status = pio_read_8(&cmd->status); 461 } while ((status & SR_BSY) != 0); 462 463 /* Write data to the disk buffer. */ 501 if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) { 502 fibril_mutex_unlock(&d->lock); 503 return EIO; 504 } 464 505 465 506 if ((status & SR_DRQ) != 0) { 507 /* Write data to the device buffer. */ 508 466 509 for (i = 0; i < block_size / 2; i++) { 467 510 pio_write_16(&cmd->data_port, ((uint16_t *) buf)[i]); … … 477 520 } 478 521 522 /** Wait until some status bits are set and some are reset. 523 * 524 * Example: wait_status(SR_DRDY, ~SR_BSY) waits for SR_DRDY to become 525 * set and SR_BSY to become reset. 526 * 527 * @param set Combination if bits which must be all set. 528 * @param n_reset Negated combination of bits which must be all reset. 529 * @param pstatus Pointer where to store last read status or NULL. 530 * @param timeout Timeout in 10ms units. 531 * 532 * @return EOK on success, EIO on timeout. 533 */ 534 static int wait_status(unsigned set, unsigned n_reset, uint8_t *pstatus, 535 unsigned timeout) 536 { 537 uint8_t status; 538 int cnt; 539 540 status = pio_read_8(&cmd->status); 541 542 /* 543 * This is crude, yet simple. First try with 1us delays 544 * (most likely the device will respond very fast). If not, 545 * start trying every 10 ms. 546 */ 547 548 cnt = 100; 549 while ((status & ~n_reset) != 0 || (status & set) != set) { 550 async_usleep(1); 551 --cnt; 552 if (cnt <= 0) break; 553 554 status = pio_read_8(&cmd->status); 555 } 556 557 cnt = timeout; 558 while ((status & ~n_reset) != 0 || (status & set) != set) { 559 async_usleep(10000); 560 --cnt; 561 if (cnt <= 0) break; 562 563 status = pio_read_8(&cmd->status); 564 } 565 566 if (pstatus) 567 *pstatus = status; 568 569 if (cnt == 0) 570 return EIO; 571 572 return EOK; 573 } 574 479 575 /** 480 576 * @} -
uspace/srv/bd/ata_bd/ata_bd.h
r42cfd91 r330965c 135 135 }; 136 136 137 /** Timeout definitions. Unit is 10 ms. */ 138 enum ata_timeout { 139 TIMEOUT_PROBE = 100, /* 1 s */ 140 TIMEOUT_BSY = 100, /* 1 s */ 141 TIMEOUT_DRDY = 1000 /* 10 s */ 142 }; 143 137 144 typedef struct { 138 145 bool present;
Note:
See TracChangeset
for help on using the changeset viewer.