+ d = &channels[idx / 2].dev[idx % 2];
+ return d->is_ata ? d : NULL;
+}
+
+disk_sector_no
+disk_size (struct disk *d)
+{
+ ASSERT (d != NULL);
+
+ return d->capacity;
+}
+
+static void
+select_sector (struct disk *d, disk_sector_no sec_no)
+{
+ struct channel *c = d->channel;
+
+ ASSERT (sec_no < d->capacity);
+ ASSERT (sec_no < (1UL << 28));
+
+ select_device_wait (d);
+ outb (reg_nsect (c), 1);
+ outb (reg_lbal (c), sec_no);
+ outb (reg_lbam (c), sec_no >> 8);
+ outb (reg_lbah (c), (sec_no >> 16));
+ outb (reg_device (c),
+ DEV_MBS | DEV_LBA | (d->device == 1 ? DEV_DEV : 0) | (sec_no >> 24));
+}
+
+void
+disk_read (struct disk *d, disk_sector_no sec_no, void *buffer)
+{
+ ASSERT (d != NULL);
+ ASSERT (buffer != NULL);
+
+ select_sector (d, sec_no);
+ execute_command (d, CMD_READ_SECTOR_RETRY);
+ wait_while_busy (d);
+ if (!input_sector (d->channel, buffer))
+ panic ("%s: disk read failed, sector=%"PRDSNu, d->name, sec_no);