+ /* Initialize channel. */
+ snprintf (c->name, sizeof c->name, "hd%zu", chan_no);
+ switch (chan_no)
+ {
+ case 0:
+ c->reg_base = 0x1f0;
+ c->irq = 14 + 0x20;
+ break;
+ case 1:
+ c->reg_base = 0x170;
+ c->irq = 15 + 0x20;
+ break;
+ default:
+ NOT_REACHED ();
+ }
+ lock_init (&c->lock, c->name);
+ c->expecting_interrupt = false;
+ sema_init (&c->completion_wait, 0, c->name);
+
+ /* Initialize devices. */
+ for (dev_no = 0; dev_no < 2; dev_no++)
+ {
+ struct disk *d = &c->devices[dev_no];
+ snprintf (d->name, sizeof d->name, "%s:%d", c->name, dev_no);
+ d->channel = c;
+ d->dev_no = dev_no;
+
+ d->is_ata = false;
+ d->capacity = 0;
+
+ d->read_cnt = d->write_cnt = 0;
+ }
+
+ /* Register interrupt handler. */
+ intr_register (c->irq, 0, INTR_OFF, interrupt_handler, c->name);
+
+ /* Reset hardware. */
+ reset_channel (c);
+
+ /* Distinguish ATA hard disks from other devices. */
+ if (check_device_type (&c->devices[0]))
+ check_device_type (&c->devices[1]);
+
+ /* Read hard disk identity information. */
+ for (dev_no = 0; dev_no < 2; dev_no++)
+ if (c->devices[dev_no].is_ata)
+ identify_ata_device (&c->devices[dev_no]);
+ }