Changes in / [330965c:42cfd91] in mainline
- Location:
- uspace/srv/bd/ata_bd
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/bd/ata_bd/ata_bd.c
r330965c r42cfd91 60 60 #define NAME "ata_bd" 61 61 62 /** Physical block size. Should be always 512. */63 62 static const size_t block_size = 512; 64 65 /** Size of the communication area. */66 63 static size_t comm_size; 67 64 68 /** I/O base address of the command registers. */69 65 static uintptr_t cmd_physical = 0x1f0; 70 /** I/O base address of the control registers. */71 66 static uintptr_t ctl_physical = 0x170; 72 73 67 static ata_cmd_t *cmd; 74 68 static ata_ctl_t *ctl; … … 86 80 const void *buf); 87 81 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);90 82 91 83 int main(int argc, char **argv) 92 84 { 85 uint8_t status; 93 86 char name[16]; 94 87 int i, rc; … … 102 95 return -1; 103 96 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 } 97 (void) drive_identify(0, &disk[0]); 98 (void) drive_identify(1, &disk[1]); 117 99 118 100 n_disks = 0; … … 147 129 } 148 130 149 150 /** Register driver and enable device I/O. */ 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 151 207 static int ata_bd_init(void) 152 208 { … … 180 236 } 181 237 182 /** Block device connection handler */183 238 static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall) 184 239 { … … 251 306 } 252 307 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_BLOCK257 * @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 */263 308 static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t blk_idx, size_t size, 264 309 void *buf) … … 292 337 } 293 338 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 */ 339 368 340 static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt, 369 341 void *buf) … … 399 371 /* Program a Read Sectors operation. */ 400 372 401 if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) { 402 fibril_mutex_unlock(&d->lock); 403 return EIO; 404 } 373 do { 374 status = pio_read_8(&cmd->status); 375 } while ((status & SR_BSY) != 0); 405 376 406 377 pio_write_8(&cmd->drive_head, drv_head); 407 378 408 if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) { 409 fibril_mutex_unlock(&d->lock); 410 return EIO; 411 } 379 do { 380 status = pio_read_8(&cmd->status); 381 } while ((status & SR_BSY) != 0 || (status & SR_DRDY) == 0); 412 382 413 383 pio_write_8(&cmd->sector_count, 1); … … 418 388 pio_write_8(&cmd->command, CMD_READ_SECTORS); 419 389 420 if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) { 421 fibril_mutex_unlock(&d->lock); 422 return EIO; 423 } 390 do { 391 status = pio_read_8(&cmd->status); 392 } while ((status & SR_BSY) != 0); 393 394 /* Read data from the disk buffer. */ 424 395 425 396 if ((status & SR_DRQ) != 0) { 426 /* Read data from the device buffer. */427 428 397 for (i = 0; i < block_size / 2; i++) { 429 398 data = pio_read_16(&cmd->data_port); … … 439 408 } 440 409 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 */450 410 static int ata_bd_write_block(int disk_id, uint64_t blk_idx, size_t blk_cnt, 451 411 const void *buf) … … 478 438 fibril_mutex_lock(&d->lock); 479 439 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 440 /* Program a Read Sectors operation. */ 441 442 do { 443 status = pio_read_8(&cmd->status); 444 } while ((status & SR_BSY) != 0); 445 487 446 pio_write_8(&cmd->drive_head, drv_head); 488 447 489 if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) { 490 fibril_mutex_unlock(&d->lock); 491 return EIO; 492 } 448 do { 449 status = pio_read_8(&cmd->status); 450 } while ((status & SR_BSY) != 0 || (status & SR_DRDY) == 0); 493 451 494 452 pio_write_8(&cmd->sector_count, 1); … … 499 457 pio_write_8(&cmd->command, CMD_WRITE_SECTORS); 500 458 501 if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) { 502 fibril_mutex_unlock(&d->lock); 503 return EIO; 504 } 459 do { 460 status = pio_read_8(&cmd->status); 461 } while ((status & SR_BSY) != 0); 462 463 /* Write data to the disk buffer. */ 505 464 506 465 if ((status & SR_DRQ) != 0) { 507 /* Write data to the device buffer. */508 509 466 for (i = 0; i < block_size / 2; i++) { 510 467 pio_write_16(&cmd->data_port, ((uint16_t *) buf)[i]); … … 520 477 } 521 478 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 become525 * 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 delays544 * (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 575 479 /** 576 480 * @} -
uspace/srv/bd/ata_bd/ata_bd.h
r330965c r42cfd91 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 144 137 typedef struct { 145 138 bool present;
Note:
See TracChangeset
for help on using the changeset viewer.