Changeset f3386d7 in mainline for uspace/drv/block/ata_bd/ata_bd.c
- Timestamp:
- 2013-07-15T20:44:54Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f8d3df3
- Parents:
- 273c976 (diff), a940f1d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/block/ata_bd/ata_bd.c
r273c976 rf3386d7 1 1 /* 2 * Copyright (c) 20 09Jiri Svoboda2 * Copyright (c) 2013 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 35 35 * @brief ATA disk driver 36 36 * 37 * This driver supports CHS, 28-bit and 48-bit LBA addressing . It only uses38 * P IO transfers. There is no support DMA, the PACKET feature set or any other39 * fancy features such as S.M.A.R.T, removable devices, etc.37 * This driver supports CHS, 28-bit and 48-bit LBA addressing, as well as 38 * PACKET devices. It only uses PIO transfers. There is no support DMA 39 * or any other fancy features such as S.M.A.R.T, removable devices, etc. 40 40 * 41 41 * This driver is based on the ATA-1, ATA-2, ATA-3 and ATA/ATAPI-4 through 7 … … 48 48 */ 49 49 50 #include <stdio.h>51 50 #include <ddi.h> 51 #include <ddf/log.h> 52 52 #include <async.h> 53 53 #include <as.h> … … 61 61 #include <errno.h> 62 62 #include <stdbool.h> 63 #include <stdio.h> 63 64 #include <byteorder.h> 64 65 #include <task.h> … … 67 68 #include "ata_hw.h" 68 69 #include "ata_bd.h" 70 #include "main.h" 69 71 70 72 #define NAME "ata_bd" … … 80 82 static const size_t identify_data_size = 512; 81 83 82 /** I/O base address of the command registers. */ 83 static uintptr_t cmd_physical; 84 /** I/O base address of the control registers. */ 85 static uintptr_t ctl_physical; 86 87 /** I/O base addresses for legacy (ISA-compatible) controllers. */ 88 static ata_base_t legacy_base[LEGACY_CTLS] = { 89 { 0x1f0, 0x3f0 }, 90 { 0x170, 0x370 }, 91 { 0x1e8, 0x3e8 }, 92 { 0x168, 0x368 } 93 }; 94 95 static ata_cmd_t *cmd; 96 static ata_ctl_t *ctl; 97 98 /** Per-disk state. */ 99 static disk_t ata_disk[MAX_DISKS]; 100 101 static void print_syntax(void); 102 static int ata_bd_init(void); 103 static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *); 84 static int ata_bd_init_io(ata_ctrl_t *ctrl); 85 static void ata_bd_fini_io(ata_ctrl_t *ctrl); 104 86 105 87 static int ata_bd_open(bd_srvs_t *, bd_srv_t *); … … 117 99 static int ata_rcmd_write(disk_t *disk, uint64_t ba, size_t cnt, 118 100 const void *buf); 119 static int disk_init( disk_t *d, int disk_id);120 static int drive_identify(disk_t *disk, void *buf);121 static int identify_pkt_dev(disk_t *disk, void *buf);101 static int disk_init(ata_ctrl_t *ctrl, disk_t *d, int disk_id); 102 static int ata_identify_dev(disk_t *disk, void *buf); 103 static int ata_identify_pkt_dev(disk_t *disk, void *buf); 122 104 static int ata_cmd_packet(disk_t *disk, const void *cpkt, size_t cpkt_size, 123 105 void *obuf, size_t obuf_size); … … 129 111 static void disk_print_summary(disk_t *d); 130 112 static int coord_calc(disk_t *d, uint64_t ba, block_coord_t *bc); 131 static void coord_sc_program(const block_coord_t *bc, uint16_t scnt); 132 static int wait_status(unsigned set, unsigned n_reset, uint8_t *pstatus, 133 unsigned timeout); 134 135 static bd_ops_t ata_bd_ops = { 113 static void coord_sc_program(ata_ctrl_t *ctrl, const block_coord_t *bc, 114 uint16_t scnt); 115 static int wait_status(ata_ctrl_t *ctrl, unsigned set, unsigned n_reset, 116 uint8_t *pstatus, unsigned timeout); 117 118 bd_ops_t ata_bd_ops = { 136 119 .open = ata_bd_open, 137 120 .close = ata_bd_close, … … 153 136 } 154 137 155 int main(int argc, char **argv) 156 { 157 char name[16]; 138 /** Initialize ATA controller. */ 139 int ata_ctrl_init(ata_ctrl_t *ctrl, ata_base_t *res) 140 { 158 141 int i, rc; 159 142 int n_disks; 160 unsigned ctl_num; 161 char *eptr; 162 163 printf(NAME ": ATA disk driver\n"); 164 165 if (argc > 1) { 166 ctl_num = strtoul(argv[1], &eptr, 0); 167 if (*eptr != '\0' || ctl_num == 0 || ctl_num > 4) { 168 printf("Invalid argument.\n"); 169 print_syntax(); 170 return -1; 171 } 172 } else { 173 ctl_num = 1; 174 } 175 176 cmd_physical = legacy_base[ctl_num - 1].cmd; 177 ctl_physical = legacy_base[ctl_num - 1].ctl; 178 179 printf("I/O address %p/%p\n", (void *) cmd_physical, 180 (void *) ctl_physical); 181 182 if (ata_bd_init() != EOK) 183 return -1; 143 144 ddf_msg(LVL_DEBUG, "ata_ctrl_init()"); 145 146 fibril_mutex_initialize(&ctrl->lock); 147 ctrl->cmd_physical = res->cmd; 148 ctrl->ctl_physical = res->ctl; 149 150 ddf_msg(LVL_NOTE, "I/O address %p/%p", (void *) ctrl->cmd_physical, 151 (void *) ctrl->ctl_physical); 152 153 rc = ata_bd_init_io(ctrl); 154 if (rc != EOK) 155 return rc; 184 156 185 157 for (i = 0; i < MAX_DISKS; i++) { 186 printf("Identify drive %d... ", i); 187 fflush(stdout); 188 189 rc = disk_init(&ata_disk[i], i); 158 ddf_msg(LVL_NOTE, "Identify drive %d...", i); 159 160 rc = disk_init(ctrl, &ctrl->disk[i], i); 190 161 191 162 if (rc == EOK) { 192 disk_print_summary(& ata_disk[i]);163 disk_print_summary(&ctrl->disk[i]); 193 164 } else { 194 printf("Not found.\n");165 ddf_msg(LVL_NOTE, "Not found."); 195 166 } 196 167 } … … 200 171 for (i = 0; i < MAX_DISKS; i++) { 201 172 /* Skip unattached drives. */ 202 if ( ata_disk[i].present == false)173 if (ctrl->disk[i].present == false) 203 174 continue; 204 205 snprintf(name, 16, "%s/ata%udisk%d", NAMESPACE, ctl_num, i); 206 rc = loc_service_register(name, &ata_disk[i].service_id); 175 176 rc = ata_fun_create(&ctrl->disk[i]); 207 177 if (rc != EOK) { 208 printf(NAME ": Unable to register device %s.\n", name); 178 ddf_msg(LVL_ERROR, "Unable to create function for " 179 "disk %d.", i); 180 goto error; 181 } 182 ++n_disks; 183 } 184 185 if (n_disks == 0) { 186 ddf_msg(LVL_WARN, "No disks detected."); 187 rc = EIO; 188 goto error; 189 } 190 191 return EOK; 192 error: 193 for (i = 0; i < MAX_DISKS; i++) { 194 if (ata_fun_remove(&ctrl->disk[i]) != EOK) { 195 ddf_msg(LVL_ERROR, "Unable to clean up function for " 196 "disk %d.", i); 197 } 198 } 199 ata_bd_fini_io(ctrl); 200 return rc; 201 } 202 203 /** Remove ATA controller. */ 204 int ata_ctrl_remove(ata_ctrl_t *ctrl) 205 { 206 int i, rc; 207 208 ddf_msg(LVL_DEBUG, ": ata_ctrl_remove()"); 209 210 fibril_mutex_lock(&ctrl->lock); 211 212 for (i = 0; i < MAX_DISKS; i++) { 213 rc = ata_fun_remove(&ctrl->disk[i]); 214 if (rc != EOK) { 215 ddf_msg(LVL_ERROR, "Unable to clean up function for " 216 "disk %d.", i); 209 217 return rc; 210 218 } 211 ++n_disks; 212 } 213 214 if (n_disks == 0) { 215 printf("No disks detected.\n"); 216 return -1; 217 } 218 219 printf("%s: Accepting connections\n", NAME); 220 task_retval(0); 221 async_manager(); 222 223 /* Not reached */ 224 return 0; 225 } 226 227 228 static void print_syntax(void) 229 { 230 printf("Syntax: " NAME " <controller_number>\n"); 231 printf("Controller number = 1..4\n"); 219 } 220 221 ata_bd_fini_io(ctrl); 222 fibril_mutex_unlock(&ctrl->lock); 223 224 return EOK; 225 } 226 227 /** Surprise removal of ATA controller. */ 228 int ata_ctrl_gone(ata_ctrl_t *ctrl) 229 { 230 int i, rc; 231 232 ddf_msg(LVL_DEBUG, "ata_ctrl_gone()"); 233 234 fibril_mutex_lock(&ctrl->lock); 235 236 for (i = 0; i < MAX_DISKS; i++) { 237 rc = ata_fun_unbind(&ctrl->disk[i]); 238 if (rc != EOK) { 239 ddf_msg(LVL_ERROR, "Unable to clean up function for " 240 "disk %d.", i); 241 return rc; 242 } 243 } 244 245 ata_bd_fini_io(ctrl); 246 fibril_mutex_unlock(&ctrl->lock); 247 248 return EOK; 232 249 } 233 250 … … 236 253 { 237 254 uint64_t mbytes; 238 239 printf("%s: ", d->model); 255 char *atype = NULL; 256 char *cap = NULL; 257 int rc; 240 258 241 259 if (d->dev_type == ata_reg_dev) { 242 260 switch (d->amode) { 243 261 case am_chs: 244 printf("CHS %u cylinders, %u heads, %u sectors",245 d->geom.cylinders, d->geom.heads,262 rc = asprintf(&atype, "CHS %u cylinders, %u heads, " 263 "%u sectors", d->geom.cylinders, d->geom.heads, 246 264 d->geom.sectors); 265 if (rc < 0) { 266 /* Out of memory */ 267 atype = NULL; 268 } 247 269 break; 248 270 case am_lba28: 249 printf("LBA-28");271 atype = str_dup("LBA-28"); 250 272 break; 251 273 case am_lba48: 252 printf("LBA-48");274 atype = str_dup("LBA-48"); 253 275 break; 254 276 } 255 277 } else { 256 printf("PACKET"); 257 } 258 259 printf(" %" PRIu64 " blocks", d->blocks); 278 atype = str_dup("PACKET"); 279 } 280 281 if (atype == NULL) 282 return; 260 283 261 284 mbytes = d->blocks / (2 * 1024); 262 if (mbytes > 0) 263 printf(" %" PRIu64 " MB.", mbytes); 264 265 printf("\n"); 266 } 267 268 /** Register driver and enable device I/O. */ 269 static int ata_bd_init(void) 270 { 271 async_set_client_connection(ata_bd_connection); 272 int rc = loc_server_register(NAME); 285 if (mbytes > 0) { 286 rc = asprintf(&cap, " %" PRIu64 " MB.", mbytes); 287 if (rc < 0) { 288 cap = NULL; 289 goto cleanup; 290 } 291 } 292 293 ddf_msg(LVL_NOTE, "%s: %s %" PRIu64 " blocks%s", d->model, atype, 294 d->blocks, cap); 295 cleanup: 296 free(atype); 297 free(cap); 298 } 299 300 /** Enable device I/O. */ 301 static int ata_bd_init_io(ata_ctrl_t *ctrl) 302 { 303 int rc; 304 void *vaddr; 305 306 rc = pio_enable((void *) ctrl->cmd_physical, sizeof(ata_cmd_t), &vaddr); 273 307 if (rc != EOK) { 274 printf("%s: Unable to register driver.\n", NAME);308 ddf_msg(LVL_ERROR, "Cannot initialize device I/O space."); 275 309 return rc; 276 310 } 277 278 void *vaddr; 279 rc = pio_enable((void *) cmd_physical, sizeof(ata_cmd_t), &vaddr); 311 312 ctrl->cmd = vaddr; 313 314 rc = pio_enable((void *) ctrl->ctl_physical, sizeof(ata_ctl_t), &vaddr); 280 315 if (rc != EOK) { 281 printf("%s: Could not initialize device I/O space.\n", NAME);316 ddf_msg(LVL_ERROR, "Cannot initialize device I/O space."); 282 317 return rc; 283 318 } 284 285 cmd = vaddr; 286 287 rc = pio_enable((void *) ctl_physical, sizeof(ata_ctl_t), &vaddr); 288 if (rc != EOK) { 289 printf("%s: Could not initialize device I/O space.\n", NAME); 290 return rc; 291 } 292 293 ctl = vaddr; 294 295 return EOK; 296 } 297 298 /** Block device connection handler */ 299 static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 300 { 301 service_id_t dsid; 302 int i; 303 disk_t *disk; 304 305 /* Get the device service ID. */ 306 dsid = IPC_GET_ARG1(*icall); 307 308 /* Determine which disk device is the client connecting to. */ 309 disk = NULL; 310 for (i = 0; i < MAX_DISKS; i++) 311 if (ata_disk[i].service_id == dsid) 312 disk = &ata_disk[i]; 313 314 if (disk == NULL || disk->present == false) { 315 async_answer_0(iid, EINVAL); 316 return; 317 } 318 319 bd_conn(iid, icall, &disk->bds); 319 320 ctrl->ctl = vaddr; 321 322 return EOK; 323 } 324 325 /** Clean up device I/O. */ 326 static void ata_bd_fini_io(ata_ctrl_t *ctrl) 327 { 328 (void) ctrl; 329 /* XXX TODO */ 320 330 } 321 331 … … 325 335 * the disk structure. 326 336 */ 327 static int disk_init( disk_t *d, int disk_id)337 static int disk_init(ata_ctrl_t *ctrl, disk_t *d, int disk_id) 328 338 { 329 339 identify_data_t idata; … … 337 347 unsigned i; 338 348 349 d->ctrl = ctrl; 339 350 d->disk_id = disk_id; 340 351 d->present = false; 341 fibril_mutex_initialize(&d->lock); 342 343 bd_srvs_init(&d->bds); 344 d->bds.ops = &ata_bd_ops; 345 d->bds.sarg = d; 352 d->afun = NULL; 346 353 347 354 /* Try identify command. */ 348 rc = drive_identify(d, &idata);355 rc = ata_identify_dev(d, &idata); 349 356 if (rc == EOK) { 350 357 /* Success. It's a register (non-packet) device. */ 351 printf("ATA register-only device found.\n");358 ddf_msg(LVL_NOTE, "ATA register-only device found."); 352 359 d->dev_type = ata_reg_dev; 353 360 } else if (rc == EIO) { … … 362 369 * the byte count registers. So, only check these. 363 370 */ 364 bc = ((uint16_t)pio_read_8(&c md->cylinder_high) << 8) |365 pio_read_8(&c md->cylinder_low);371 bc = ((uint16_t)pio_read_8(&ctrl->cmd->cylinder_high) << 8) | 372 pio_read_8(&ctrl->cmd->cylinder_low); 366 373 367 374 if (bc == PDEV_SIGNATURE_BC) { 368 rc = identify_pkt_dev(d, &idata);375 rc = ata_identify_pkt_dev(d, &idata); 369 376 if (rc == EOK) { 370 377 /* We have a packet device. */ … … 452 459 rc = ata_pcmd_inquiry(d, &inq_data, sizeof(inq_data)); 453 460 if (rc != EOK) { 454 printf("Device inquiry failed.\n");461 ddf_msg(LVL_ERROR, "Device inquiry failed."); 455 462 d->present = false; 456 463 return EIO; … … 459 466 /* Check device type. */ 460 467 if (INQUIRY_PDEV_TYPE(inq_data.pdev_type) != PDEV_TYPE_CDROM) 461 printf("Warning: Peripheral device type is not CD-ROM.\n");468 ddf_msg(LVL_WARN, "Peripheral device type is not CD-ROM."); 462 469 463 470 /* Assume 2k block size for now. */ … … 563 570 } 564 571 565 /** Issue IDENTIFY command. 572 /** PIO data-in command protocol. */ 573 static int ata_pio_data_in(disk_t *disk, void *obuf, size_t obuf_size, 574 size_t blk_size, size_t nblocks) 575 { 576 ata_ctrl_t *ctrl = disk->ctrl; 577 uint16_t data; 578 size_t i; 579 uint8_t status; 580 581 /* XXX Support multiple blocks */ 582 assert(nblocks == 1); 583 assert(blk_size % 2 == 0); 584 585 if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) 586 return EIO; 587 588 if ((status & SR_DRQ) != 0) { 589 /* Read data from the device buffer. */ 590 591 for (i = 0; i < blk_size / 2; i++) { 592 data = pio_read_16(&ctrl->cmd->data_port); 593 ((uint16_t *) obuf)[i] = data; 594 } 595 } 596 597 if ((status & SR_ERR) != 0) 598 return EIO; 599 600 return EOK; 601 } 602 603 /** PIO data-out command protocol. */ 604 static int ata_pio_data_out(disk_t *disk, const void *buf, size_t buf_size, 605 size_t blk_size, size_t nblocks) 606 { 607 ata_ctrl_t *ctrl = disk->ctrl; 608 size_t i; 609 uint8_t status; 610 611 /* XXX Support multiple blocks */ 612 assert(nblocks == 1); 613 assert(blk_size % 2 == 0); 614 615 if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) 616 return EIO; 617 618 if ((status & SR_DRQ) != 0) { 619 /* Write data to the device buffer. */ 620 621 for (i = 0; i < blk_size / 2; i++) { 622 pio_write_16(&ctrl->cmd->data_port, ((uint16_t *) buf)[i]); 623 } 624 } 625 626 if (status & SR_ERR) 627 return EIO; 628 629 return EOK; 630 } 631 632 /** Issue IDENTIFY DEVICE command. 566 633 * 567 634 * Reads @c identify data into the provided buffer. This is used to detect … … 574 641 * not present). EIO if device responds with error. 575 642 */ 576 static int drive_identify(disk_t *disk, void *buf)577 { 578 uint16_t data;643 static int ata_identify_dev(disk_t *disk, void *buf) 644 { 645 ata_ctrl_t *ctrl = disk->ctrl; 579 646 uint8_t status; 580 647 uint8_t drv_head; 581 size_t i;582 648 583 649 drv_head = ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0); 584 650 585 if (wait_status( 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)651 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) 586 652 return ETIMEOUT; 587 653 588 pio_write_8(&c md->drive_head, drv_head);654 pio_write_8(&ctrl->cmd->drive_head, drv_head); 589 655 590 656 /* … … 593 659 * set after issuing the command. 594 660 */ 595 if (wait_status( 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)661 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) 596 662 return ETIMEOUT; 597 663 598 pio_write_8(&c md->command, CMD_IDENTIFY_DRIVE);599 600 if (wait_status( 0, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK)664 pio_write_8(&ctrl->cmd->command, CMD_IDENTIFY_DRIVE); 665 666 if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK) 601 667 return ETIMEOUT; 602 668 … … 605 671 * the caller to check for one. 606 672 */ 607 if ((status & SR_ERR) != 0) { 608 return EIO; 609 } 610 611 if (wait_status(SR_DRQ, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK) 673 if ((status & SR_ERR) != 0) 674 return EIO; 675 676 /* 677 * For probing purposes we need to wait for some status bit to become 678 * active - otherwise we could be fooled just by receiving all zeroes. 679 */ 680 if (wait_status(ctrl, SR_DRQ, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK) 612 681 return ETIMEOUT; 613 682 614 /* Read data from the disk buffer. */ 615 616 for (i = 0; i < identify_data_size / 2; i++) { 617 data = pio_read_16(&cmd->data_port); 618 ((uint16_t *) buf)[i] = data; 619 } 620 621 return EOK; 683 return ata_pio_data_in(disk, buf, identify_data_size, 684 identify_data_size, 1); 622 685 } 623 686 … … 630 693 * @param buf Pointer to a 512-byte buffer. 631 694 */ 632 static int identify_pkt_dev(disk_t *disk, void *buf) 633 { 634 uint16_t data; 635 uint8_t status; 695 static int ata_identify_pkt_dev(disk_t *disk, void *buf) 696 { 697 ata_ctrl_t *ctrl = disk->ctrl; 636 698 uint8_t drv_head; 637 size_t i;638 699 639 700 drv_head = ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0); 640 701 641 if (wait_status( 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)642 return EIO; 643 644 pio_write_8(&c md->drive_head, drv_head);702 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) 703 return EIO; 704 705 pio_write_8(&ctrl->cmd->drive_head, drv_head); 645 706 646 707 /* For ATAPI commands we do not need to wait for DRDY. */ 647 if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) 648 return EIO; 649 650 pio_write_8(&cmd->command, CMD_IDENTIFY_PKT_DEV); 651 652 if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) 653 return EIO; 654 655 /* Read data from the device buffer. */ 656 657 if ((status & SR_DRQ) != 0) { 658 for (i = 0; i < identify_data_size / 2; i++) { 659 data = pio_read_16(&cmd->data_port); 660 ((uint16_t *) buf)[i] = data; 661 } 662 } 663 664 if ((status & SR_ERR) != 0) 665 return EIO; 666 667 return EOK; 708 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) 709 return EIO; 710 711 pio_write_8(&ctrl->cmd->command, CMD_IDENTIFY_PKT_DEV); 712 713 return ata_pio_data_in(disk, buf, identify_data_size, 714 identify_data_size, 1); 668 715 } 669 716 … … 681 728 void *obuf, size_t obuf_size) 682 729 { 730 ata_ctrl_t *ctrl = disk->ctrl; 683 731 size_t i; 684 732 uint8_t status; … … 687 735 uint16_t val; 688 736 689 fibril_mutex_lock(& disk->lock);737 fibril_mutex_lock(&ctrl->lock); 690 738 691 739 /* New value for Drive/Head register */ … … 693 741 ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0); 694 742 695 if (wait_status( 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) {696 fibril_mutex_unlock(& disk->lock);697 return EIO; 698 } 699 700 pio_write_8(&c md->drive_head, drv_head);701 702 if (wait_status( 0, ~(SR_BSY|SR_DRQ), NULL, TIMEOUT_BSY) != EOK) {703 fibril_mutex_unlock(& disk->lock);743 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) { 744 fibril_mutex_unlock(&ctrl->lock); 745 return EIO; 746 } 747 748 pio_write_8(&ctrl->cmd->drive_head, drv_head); 749 750 if (wait_status(ctrl, 0, ~(SR_BSY|SR_DRQ), NULL, TIMEOUT_BSY) != EOK) { 751 fibril_mutex_unlock(&ctrl->lock); 704 752 return EIO; 705 753 } 706 754 707 755 /* Byte count <- max. number of bytes we can read in one transfer. */ 708 pio_write_8(&c md->cylinder_low, 0xfe);709 pio_write_8(&c md->cylinder_high, 0xff);710 711 pio_write_8(&c md->command, CMD_PACKET);712 713 if (wait_status( SR_DRQ, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {714 fibril_mutex_unlock(& disk->lock);756 pio_write_8(&ctrl->cmd->cylinder_low, 0xfe); 757 pio_write_8(&ctrl->cmd->cylinder_high, 0xff); 758 759 pio_write_8(&ctrl->cmd->command, CMD_PACKET); 760 761 if (wait_status(ctrl, SR_DRQ, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) { 762 fibril_mutex_unlock(&ctrl->lock); 715 763 return EIO; 716 764 } … … 718 766 /* Write command packet. */ 719 767 for (i = 0; i < (cpkt_size + 1) / 2; i++) 720 pio_write_16(&c md->data_port, ((uint16_t *) cpkt)[i]);721 722 if (wait_status( 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {723 fibril_mutex_unlock(& disk->lock);768 pio_write_16(&ctrl->cmd->data_port, ((uint16_t *) cpkt)[i]); 769 770 if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) { 771 fibril_mutex_unlock(&ctrl->lock); 724 772 return EIO; 725 773 } 726 774 727 775 if ((status & SR_DRQ) == 0) { 728 fibril_mutex_unlock(& disk->lock);776 fibril_mutex_unlock(&ctrl->lock); 729 777 return EIO; 730 778 } 731 779 732 780 /* Read byte count. */ 733 data_size = (uint16_t) pio_read_8(&c md->cylinder_low) +734 ((uint16_t) pio_read_8(&c md->cylinder_high) << 8);781 data_size = (uint16_t) pio_read_8(&ctrl->cmd->cylinder_low) + 782 ((uint16_t) pio_read_8(&ctrl->cmd->cylinder_high) << 8); 735 783 736 784 /* Check whether data fits into output buffer. */ 737 785 if (data_size > obuf_size) { 738 786 /* Output buffer is too small to store data. */ 739 fibril_mutex_unlock(& disk->lock);787 fibril_mutex_unlock(&ctrl->lock); 740 788 return EIO; 741 789 } … … 743 791 /* Read data from the device buffer. */ 744 792 for (i = 0; i < (data_size + 1) / 2; i++) { 745 val = pio_read_16(&c md->data_port);793 val = pio_read_16(&ctrl->cmd->data_port); 746 794 ((uint16_t *) obuf)[i] = val; 747 795 } 748 796 749 if (status & SR_ERR) { 750 fibril_mutex_unlock(&disk->lock); 751 return EIO; 752 } 753 754 fibril_mutex_unlock(&disk->lock); 797 fibril_mutex_unlock(&ctrl->lock); 798 799 if (status & SR_ERR) 800 return EIO; 755 801 756 802 return EOK; … … 849 895 cp.oldformat = 0x40; /* 0x01 = multi-session mode (shifted to MSB) */ 850 896 851 rc = ata_cmd_packet( 0, &cp, sizeof(cp), obuf, obuf_size);897 rc = ata_cmd_packet(disk, &cp, sizeof(cp), obuf, obuf_size); 852 898 if (rc != EOK) 853 899 return rc; … … 856 902 } 857 903 858 /** Read a physical from the device.904 /** Read a physical block from the device. 859 905 * 860 906 * @param disk Disk … … 868 914 void *buf) 869 915 { 870 size_t i; 871 uint16_t data; 872 uint8_t status; 916 ata_ctrl_t *ctrl = disk->ctrl; 873 917 uint8_t drv_head; 874 918 block_coord_t bc; 919 int rc; 875 920 876 921 /* Silence warning. */ … … 887 932 (bc.h & 0x0f); 888 933 889 fibril_mutex_lock(& disk->lock);934 fibril_mutex_lock(&ctrl->lock); 890 935 891 936 /* Program a Read Sectors operation. */ 892 937 893 if (wait_status( 0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {894 fibril_mutex_unlock(& disk->lock);895 return EIO; 896 } 897 898 pio_write_8(&c md->drive_head, drv_head);899 900 if (wait_status( SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {901 fibril_mutex_unlock(& disk->lock);938 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) { 939 fibril_mutex_unlock(&ctrl->lock); 940 return EIO; 941 } 942 943 pio_write_8(&ctrl->cmd->drive_head, drv_head); 944 945 if (wait_status(ctrl, SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) { 946 fibril_mutex_unlock(&ctrl->lock); 902 947 return EIO; 903 948 } 904 949 905 950 /* Program block coordinates into the device. */ 906 coord_sc_program( &bc, 1);907 908 pio_write_8(&c md->command, disk->amode == am_lba48 ?951 coord_sc_program(ctrl, &bc, 1); 952 953 pio_write_8(&ctrl->cmd->command, disk->amode == am_lba48 ? 909 954 CMD_READ_SECTORS_EXT : CMD_READ_SECTORS); 910 955 911 if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) { 912 fibril_mutex_unlock(&disk->lock); 913 return EIO; 914 } 915 916 if ((status & SR_DRQ) != 0) { 917 /* Read data from the device buffer. */ 918 919 for (i = 0; i < disk->block_size / 2; i++) { 920 data = pio_read_16(&cmd->data_port); 921 ((uint16_t *) buf)[i] = data; 922 } 923 } 924 925 if ((status & SR_ERR) != 0) 926 return EIO; 927 928 fibril_mutex_unlock(&disk->lock); 929 return EOK; 956 rc = ata_pio_data_in(disk, buf, blk_cnt * disk->block_size, 957 disk->block_size, blk_cnt); 958 959 fibril_mutex_unlock(&ctrl->lock); 960 961 return rc; 930 962 } 931 963 … … 942 974 const void *buf) 943 975 { 944 size_t i; 945 uint8_t status; 976 ata_ctrl_t *ctrl = disk->ctrl; 946 977 uint8_t drv_head; 947 978 block_coord_t bc; 979 int rc; 948 980 949 981 /* Silence warning. */ … … 960 992 (bc.h & 0x0f); 961 993 962 fibril_mutex_lock(& disk->lock);994 fibril_mutex_lock(&ctrl->lock); 963 995 964 996 /* Program a Write Sectors operation. */ 965 997 966 if (wait_status( 0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {967 fibril_mutex_unlock(& disk->lock);968 return EIO; 969 } 970 971 pio_write_8(&c md->drive_head, drv_head);972 973 if (wait_status( SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {974 fibril_mutex_unlock(& disk->lock);998 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) { 999 fibril_mutex_unlock(&ctrl->lock); 1000 return EIO; 1001 } 1002 1003 pio_write_8(&ctrl->cmd->drive_head, drv_head); 1004 1005 if (wait_status(ctrl, SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) { 1006 fibril_mutex_unlock(&ctrl->lock); 975 1007 return EIO; 976 1008 } 977 1009 978 1010 /* Program block coordinates into the device. */ 979 coord_sc_program( &bc, 1);980 981 pio_write_8(&c md->command, disk->amode == am_lba48 ?1011 coord_sc_program(ctrl, &bc, 1); 1012 1013 pio_write_8(&ctrl->cmd->command, disk->amode == am_lba48 ? 982 1014 CMD_WRITE_SECTORS_EXT : CMD_WRITE_SECTORS); 983 1015 984 if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) { 985 fibril_mutex_unlock(&disk->lock); 986 return EIO; 987 } 988 989 if ((status & SR_DRQ) != 0) { 990 /* Write data to the device buffer. */ 991 992 for (i = 0; i < disk->block_size / 2; i++) { 993 pio_write_16(&cmd->data_port, ((uint16_t *) buf)[i]); 994 } 995 } 996 997 fibril_mutex_unlock(&disk->lock); 998 999 if (status & SR_ERR) 1000 return EIO; 1001 1002 return EOK; 1016 rc = ata_pio_data_out(disk, buf, cnt * disk->block_size, 1017 disk->block_size, cnt); 1018 1019 fibril_mutex_unlock(&ctrl->lock); 1020 return rc; 1003 1021 } 1004 1022 … … 1060 1078 * 1061 1079 * Note that bc->h must be programmed separately into the device/head register. 1062 */ 1063 static void coord_sc_program(const block_coord_t *bc, uint16_t scnt) 1064 { 1080 * 1081 * @param ctrl Controller 1082 * @param bc Block coordinates 1083 * @param scnt Sector count 1084 */ 1085 static void coord_sc_program(ata_ctrl_t *ctrl, const block_coord_t *bc, 1086 uint16_t scnt) 1087 { 1088 ata_cmd_t *cmd = ctrl->cmd; 1089 1065 1090 if (bc->amode == am_lba48) { 1066 1091 /* Write high-order bits. */ … … 1080 1105 /** Wait until some status bits are set and some are reset. 1081 1106 * 1082 * Example: wait_status( SR_DRDY, ~SR_BSY) waits for SR_DRDY to become1107 * Example: wait_status(ctrl, SR_DRDY, ~SR_BSY, ...) waits for SR_DRDY to become 1083 1108 * set and SR_BSY to become reset. 1084 1109 * 1110 * @param ctrl Controller 1085 1111 * @param set Combination if bits which must be all set. 1086 1112 * @param n_reset Negated combination of bits which must be all reset. … … 1090 1116 * @return EOK on success, EIO on timeout. 1091 1117 */ 1092 static int wait_status( unsigned set, unsigned n_reset, uint8_t *pstatus,1093 u nsigned timeout)1118 static int wait_status(ata_ctrl_t *ctrl, unsigned set, unsigned n_reset, 1119 uint8_t *pstatus, unsigned timeout) 1094 1120 { 1095 1121 uint8_t status; 1096 1122 int cnt; 1097 1123 1098 status = pio_read_8(&c md->status);1124 status = pio_read_8(&ctrl->cmd->status); 1099 1125 1100 1126 /* … … 1110 1136 if (cnt <= 0) break; 1111 1137 1112 status = pio_read_8(&c md->status);1138 status = pio_read_8(&ctrl->cmd->status); 1113 1139 } 1114 1140 … … 1119 1145 if (cnt <= 0) break; 1120 1146 1121 status = pio_read_8(&c md->status);1147 status = pio_read_8(&ctrl->cmd->status); 1122 1148 } 1123 1149
Note:
See TracChangeset
for help on using the changeset viewer.