Changeset 54d0ddc in mainline
- Timestamp:
- 2009-08-08T14:04:07Z (16 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 31de325
- Parents:
- d5f8f19
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/bd/ata_bd/ata_bd.c
rd5f8f19 r54d0ddc 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 uint8_t wait_status(unsigned set, unsigned n_reset); 82 89 83 90 int main(int argc, char **argv) 84 91 { 85 uint8_t status;86 92 char name[16]; 87 93 int i, rc; … … 129 135 } 130 136 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 137 138 /** Register driver and enable device I/O. */ 207 139 static int ata_bd_init(void) 208 140 { … … 236 168 } 237 169 170 /** Block device connection handler */ 238 171 static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall) 239 172 { … … 306 239 } 307 240 241 /** Transfer a logical block from/to the device. 242 * 243 * @param disk_id Device index (0 or 1) 244 * @param method @c BD_READ_BLOCK or @c BD_WRITE_BLOCK 245 * @param blk_idx Index of the first block. 246 * @param size Size of the logical block. 247 * @param buf Data buffer. 248 * 249 * @return EOK on success, EIO on error. 250 */ 308 251 static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t blk_idx, size_t size, 309 252 void *buf) … … 337 280 } 338 281 339 282 /** Issue IDENTIFY command. 283 * 284 * This is used to detect whether an ATA device is present and if so, 285 * to determine its parameters. The parameters are written to @a d. 286 * 287 * @param disk_id Device ID, 0 or 1. 288 * @param d Device structure to store parameters in. 289 */ 290 static int drive_identify(int disk_id, disk_t *d) 291 { 292 uint16_t data; 293 uint8_t status; 294 uint8_t drv_head; 295 size_t i; 296 297 printf("Identify drive %d... ", disk_id); 298 fflush(stdout); 299 300 drv_head = ((disk_id != 0) ? DHR_DRV : 0); 301 d->present = false; 302 303 wait_status(0, ~SR_BSY); 304 pio_write_8(&cmd->drive_head, drv_head); 305 306 /* 307 * Detect if drive is present. This is only temorary. 308 * We should really try for some time before giving up. 309 */ 310 status = wait_status(0, ~SR_BSY); 311 312 if ((status & SR_DRDY) == 0) { 313 printf("None attached.\n"); 314 return ENOENT; 315 } 316 /***/ 317 318 wait_status(SR_DRDY, ~SR_BSY); 319 pio_write_8(&cmd->command, CMD_IDENTIFY_DRIVE); 320 321 status = wait_status(0, ~SR_BSY); 322 323 /* Read data from the disk buffer. */ 324 325 if ((status & SR_DRQ) != 0) { 326 // for (i = 0; i < block_size / 2; i++) { 327 // data = pio_read_16(&cmd->data_port); 328 // ((uint16_t *) buf)[i] = data; 329 // } 330 331 for (i = 0; i < block_size / 2; i++) { 332 data = pio_read_16(&cmd->data_port); 333 334 switch (i) { 335 case 1: d->cylinders = data; break; 336 case 3: d->heads = data; break; 337 case 6: d->sectors = data; break; 338 } 339 } 340 } 341 342 if ((status & SR_ERR) != 0) 343 return EIO; 344 345 d->blocks = d->cylinders * d->heads * d->sectors; 346 347 printf("Geometry: %u cylinders, %u heads, %u sectors\n", 348 d->cylinders, d->heads, d->sectors); 349 350 d->present = true; 351 fibril_mutex_initialize(&d->lock); 352 353 return EOK; 354 } 355 356 /** Read a physical from the device. 357 * 358 * @param disk_id Device index (0 or 1) 359 * @param blk_idx Index of the first block. 360 * @param blk_cnt Number of blocks to transfer. 361 * @param buf Buffer for holding the data. 362 * 363 * @return EOK on success, EIO on error. 364 */ 340 365 static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt, 341 366 void *buf) … … 371 396 /* Program a Read Sectors operation. */ 372 397 373 do { 374 status = pio_read_8(&cmd->status); 375 } while ((status & SR_BSY) != 0); 376 398 wait_status(0, ~SR_BSY); 377 399 pio_write_8(&cmd->drive_head, drv_head); 378 400 379 do { 380 status = pio_read_8(&cmd->status); 381 } while ((status & SR_BSY) != 0 || (status & SR_DRDY) == 0); 382 401 wait_status(SR_DRDY, ~SR_BSY); 383 402 pio_write_8(&cmd->sector_count, 1); 384 403 pio_write_8(&cmd->sector_number, s); … … 388 407 pio_write_8(&cmd->command, CMD_READ_SECTORS); 389 408 390 do { 391 status = pio_read_8(&cmd->status); 392 } while ((status & SR_BSY) != 0); 409 status = wait_status(0, ~SR_BSY); 393 410 394 411 /* Read data from the disk buffer. */ … … 408 425 } 409 426 427 /** Write a physical block to the device. 428 * 429 * @param disk_id Device index (0 or 1) 430 * @param blk_idx Index of the first block. 431 * @param blk_cnt Number of blocks to transfer. 432 * @param buf Buffer holding the data to write. 433 * 434 * @return EOK on success, EIO on error. 435 */ 410 436 static int ata_bd_write_block(int disk_id, uint64_t blk_idx, size_t blk_cnt, 411 437 const void *buf) … … 440 466 /* Program a Read Sectors operation. */ 441 467 442 do { 443 status = pio_read_8(&cmd->status); 444 } while ((status & SR_BSY) != 0); 445 468 wait_status(0, ~SR_BSY); 446 469 pio_write_8(&cmd->drive_head, drv_head); 447 470 448 do { 449 status = pio_read_8(&cmd->status); 450 } while ((status & SR_BSY) != 0 || (status & SR_DRDY) == 0); 451 471 wait_status(SR_DRDY, ~SR_BSY); 452 472 pio_write_8(&cmd->sector_count, 1); 453 473 pio_write_8(&cmd->sector_number, s); … … 457 477 pio_write_8(&cmd->command, CMD_WRITE_SECTORS); 458 478 459 do { 460 status = pio_read_8(&cmd->status); 461 } while ((status & SR_BSY) != 0); 479 status = wait_status(0, ~SR_BSY); 462 480 463 481 /* Write data to the disk buffer. */ … … 477 495 } 478 496 497 /** Wait until some status bits are set and some reset. 498 * 499 * Example: wait_status(SR_DRDY, ~SR_BSY) waits for SR_DRDY to become 500 * set and SR_BSY to become reset. 501 * 502 * @param set Combination if bits which must be all set. 503 * @param n_reset Negated combination of bits which must be all reset. 504 * @return The last value of status register that was read. 505 */ 506 static uint8_t wait_status(unsigned set, unsigned n_reset) 507 { 508 uint8_t status; 509 510 do { 511 status = pio_read_8(&cmd->status); 512 } while ((status & ~n_reset) != 0 || (status & set) != set); 513 514 return status; 515 } 516 479 517 /** 480 518 * @}
Note:
See TracChangeset
for help on using the changeset viewer.