static void ata_boot_attach(void) { struct ata_channel *ch; int ctlr; get_mplock(); /* kick of probe and attach on all channels */ for (ctlr = 0; ctlr < devclass_get_maxunit(ata_devclass); ctlr++) { if ((ch = devclass_get_softc(ata_devclass, ctlr))) { ata_identify(ch->dev); } } rel_mplock(); }
int ata_attach(device_t dev) { struct ata_channel *ch = device_get_softc(dev); int error, rid; /* check that we have a virgin channel to attach */ if (ch->r_irq) return EEXIST; /* initialize the softc basics */ ch->dev = dev; ch->state = ATA_IDLE; bzero(&ch->state_mtx, sizeof(struct mtx)); mtx_init(&ch->state_mtx, "ATA state lock", NULL, MTX_DEF); bzero(&ch->queue_mtx, sizeof(struct mtx)); mtx_init(&ch->queue_mtx, "ATA queue lock", NULL, MTX_DEF); TAILQ_INIT(&ch->ata_queue); /* reset the controller HW, the channel and device(s) */ while (ATA_LOCKING(dev, ATA_LF_LOCK) != ch->unit) pause("ataatch", 1); ATA_RESET(dev); ATA_LOCKING(dev, ATA_LF_UNLOCK); /* setup interrupt delivery */ rid = ATA_IRQ_RID; ch->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); if (!ch->r_irq) { device_printf(dev, "unable to allocate interrupt\n"); return ENXIO; } if ((error = bus_setup_intr(dev, ch->r_irq, ATA_INTR_FLAGS, NULL, ata_interrupt, ch, &ch->ih))) { device_printf(dev, "unable to setup interrupt\n"); return error; } /* probe and attach devices on this channel unless we are in early boot */ if (!ata_delayed_attach) ata_identify(dev); return 0; }
int ata_attach(device_t dev) { struct ata_channel *ch = device_get_softc(dev); int error, rid; /* check that we have a virgin channel to attach */ if (ch->r_irq) return EEXIST; /* initialize the softc basics */ ch->dev = dev; ch->state = ATA_IDLE; lockinit(&ch->state_mtx, "ataattach_state", 0, 0); lockinit(&ch->queue_mtx, "ataattach_queue", 0, 0); ata_queue_init(ch); /* reset the controller HW, the channel and device(s) */ while (ATA_LOCKING(dev, ATA_LF_LOCK) != ch->unit) tsleep(&error, 0, "ataatch", 1); ATA_RESET(dev); ATA_LOCKING(dev, ATA_LF_UNLOCK); /* setup interrupt delivery */ rid = ATA_IRQ_RID; ch->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); if (!ch->r_irq) { device_printf(dev, "unable to allocate interrupt\n"); return ENXIO; } if ((error = bus_setup_intr(dev, ch->r_irq, ATA_INTR_FLAGS, (driver_intr_t *)ata_interrupt, ch, &ch->ih, NULL))) { device_printf(dev, "unable to setup interrupt\n"); return error; } /* probe and attach devices on this channel unless we are in early boot */ ata_identify(dev); return 0; }
void kmain(ol_mmap_register_t mmr) { textinit(); clearscreen(); println("The openLoader kernel is executing. \n"); print("Current stack pointer: "); ol_registers_t regs = getregs(); printnum(regs->esp, 16, FALSE, FALSE); putc(0xa); char status = inb(0x60); if((status & 2) == 2) { println("The A20 gate is open."); putc(0xa); } pic_init(); setIDT(); outb(OL_KBC_COMMAND, OL_KB_INIT); // enable the keyboard // display mmap init_mmap(mmr); println("Multiboot memory map:\n"); display_mmap(mmr); #if 0 uint8_t active = ide_init(bootdrive); ide_read(0x100, 1<<20, &bootdrive[active], 60); uint8_t eax = ata_identify(); printnum(active, 16, FALSE, FALSE); #endif putc(0xa); println("Waiting for service interrupts.."); while(1) halt(); println("End of program reached!"); endprogram(); }
/* $$ $$ XXX ata_readsectors is for Primary Controller $$ */ void ata_readsectors(unsigned char drive, unsigned int lba, unsigned char num_sectors, unsigned char *in_buffer ) { unsigned short *sector_buffer_pointer; unsigned int cylinder, head, sector; unsigned char Laufwerk=(drive==0 ? 0xa0:0xb0); unsigned int i; unsigned char d; if ((sectors_per_track[drive]==0) || (numheads[drive]==0)) { ata_identify(); } ata_lba2chs(lba, &cylinder, &head, §or, drive); sector_buffer_pointer=(unsigned short*) in_buffer; ata_waitbsy(); IRQ14_called=0; outportb(REG_SEKTORENZAHL, num_sectors); // Anzahl der zu lesenden Sektoren outportb(REG_SEKTORNUMMER, sector); // Sektornummer outportb(REG_ZYLINDER_LSB, cylinder & 0xff); // Zylinder LSB LSB+MSB=10Bit outportb(REG_ZYLINDER_MSB, cylinder & 0x300); // Zylinder MSB outportb(REG_LAUFWERK_KOPF, Laufwerk+head); // Laufwerk/Kopf, enthält den Kopf und das Laufwerk outportb(REG_BEFEHL, CMD_SEKTORENLESEN); while (IRQ14_called != 1); for (i=0; i<num_sectors; i++) { ata_read_pio_sector(sector_buffer_pointer); sector_buffer_pointer+=256; } ata_waitbsy(); }
static int ata_usbchannel_attach(device_t dev) { struct ata_channel *ch = device_get_softc(dev); /* initialize the softc basics */ ch->dev = dev; ch->state = ATA_IDLE; ch->hw.begin_transaction = ata_usbchannel_begin_transaction; ch->hw.end_transaction = ata_usbchannel_end_transaction; ch->hw.status = NULL; ch->hw.command = NULL; spin_init(&ch->state_mtx); spin_init(&ch->queue_mtx); ata_queue_init(ch); /* XXX SOS reset the controller HW, the channel and device(s) */ /* ATA_RESET(dev); */ /* probe and attach device on this channel */ ch->devices = ATA_ATAPI_MASTER; ata_identify(dev); return 0; }
static void ata_boot_attach(void) { struct ata_channel *ch; int ctlr; mtx_lock(&Giant); /* newbus suckage it needs Giant */ /* kick of probe and attach on all channels */ for (ctlr = 0; ctlr < devclass_get_maxunit(ata_devclass); ctlr++) { if ((ch = devclass_get_softc(ata_devclass, ctlr))) { ata_identify(ch->dev); } } /* release the hook that got us here, we are only needed once during boot */ if (ata_delayed_attach) { config_intrhook_disestablish(ata_delayed_attach); free(ata_delayed_attach, M_TEMP); ata_delayed_attach = NULL; } mtx_unlock(&Giant); /* newbus suckage dealt with, release Giant */ }
static int ata_power_up(void) { ata_set_active(); if (ata_powered) return 0; ide_power_enable(true); long spinup_start = current_tick; if (ceata) { PWRCON(0) &= ~(1 << 9); SDCI_RESET = 0xa5; sleep(HZ / 100); *((uint32_t volatile*)0x3cf00380) = 0; *((uint32_t volatile*)0x3cf0010c) = 0xff; SDCI_CTRL = SDCI_CTRL_SDCIEN | SDCI_CTRL_CLK_SEL_SDCLK | SDCI_CTRL_BIT_8 | SDCI_CTRL_BIT_14; SDCI_CDIV = SDCI_CDIV_CLKDIV(260); *((uint32_t volatile*)0x3cf00200) = 0xb000f; SDCI_IRQ_MASK = SDCI_IRQ_MASK_MASK_DAT_DONE_INT | SDCI_IRQ_MASK_MASK_IOCARD_IRQ_INT; PASS_RC(mmc_init(), 2, 0); SDCI_CDIV = SDCI_CDIV_CLKDIV(4); sleep(HZ / 100); PASS_RC(ceata_init(8), 2, 1); PASS_RC(ata_identify(ata_identify_data), 2, 2); dma_mode = 0x44; } else { PWRCON(0) &= ~(1 << 5); ATA_CFG = BIT(0); sleep(HZ / 100); ATA_CFG = 0; sleep(HZ / 100); ATA_SWRST = BIT(0); sleep(HZ / 100); ATA_SWRST = 0; sleep(HZ / 10); ATA_CONTROL = BIT(0); sleep(HZ / 5); ATA_PIO_TIME = 0x191f7; ATA_PIO_LHR = 0; if (!ata_swap) ATA_CFG = BIT(6); while (!(ATA_PIO_READY & BIT(1))) yield(); PASS_RC(ata_identify(ata_identify_data), 2, 0); uint32_t piotime = 0x11f3; uint32_t mdmatime = 0x1c175; uint32_t udmatime = 0x5071152; uint32_t param = 0; ata_dma_flags = 0; ata_lba48 = ata_identify_data[83] & BIT(10) ? true : false; if (ata_identify_data[53] & BIT(1)) { if (ata_identify_data[64] & BIT(1)) piotime = 0x2072; else if (ata_identify_data[64] & BIT(0)) piotime = 0x7083; } if (ata_identify_data[63] & BIT(2)) { mdmatime = 0x5072; param = 0x22; } else if (ata_identify_data[63] & BIT(1)) { mdmatime = 0x7083; param = 0x21; } if (ata_identify_data[63] & BITRANGE(0, 2)) { ata_dma_flags = BIT(3) | BIT(10); param |= 0x20; } if (ata_identify_data[53] & BIT(2)) { if (ata_identify_data[88] & BIT(4)) { udmatime = 0x2010a52; param = 0x44; } else if (ata_identify_data[88] & BIT(3)) { udmatime = 0x2020a52; param = 0x43; } else if (ata_identify_data[88] & BIT(2)) { udmatime = 0x3030a52; param = 0x42; } else if (ata_identify_data[88] & BIT(1)) { udmatime = 0x3050a52; param = 0x41; } if (ata_identify_data[88] & BITRANGE(0, 4)) { ata_dma_flags = BIT(2) | BIT(3) | BIT(9) | BIT(10); param |= 0x40; } } ata_dma = param ? true : false; dma_mode = param; PASS_RC(ata_set_feature(0xef, param), 2, 1); if (ata_identify_data[82] & BIT(5)) PASS_RC(ata_set_feature(0x02, 0), 2, 2); if (ata_identify_data[82] & BIT(6)) PASS_RC(ata_set_feature(0x55, 0), 2, 3); ATA_PIO_TIME = piotime; ATA_MDMA_TIME = mdmatime; ATA_UDMA_TIME = udmatime; } spinup_time = current_tick - spinup_start; if (ata_lba48) ata_total_sectors = ata_identify_data[100] | (((uint64_t)ata_identify_data[101]) << 16) | (((uint64_t)ata_identify_data[102]) << 32) | (((uint64_t)ata_identify_data[103]) << 48); else ata_total_sectors = ata_identify_data[60] | (((uint32_t)ata_identify_data[61]) << 16); ata_total_sectors >>= 3; ata_powered = true; ata_set_active(); return 0; }
static struct sk_buff * ata(struct aoedev *d, struct sk_buff *skb) { struct aoe_hdr *aoe; struct aoe_atahdr *ata; struct aoereq *rq, *e; struct bio *bio; sector_t lba; int len, rw; struct page *page; ulong bcnt, offset; aoe = (struct aoe_hdr *) skb_mac_header(skb); ata = (struct aoe_atahdr *) aoe->data; lba = readlba(ata->lba); len = sizeof *aoe + sizeof *ata; switch (ata->cmdstat) { do { case ATA_CMD_PIO_READ: lba &= ATA_LBA28MAX; case ATA_CMD_PIO_READ_EXT: lba &= 0x0000FFFFFFFFFFFFULL; rw = READ; break; case ATA_CMD_PIO_WRITE: lba &= ATA_LBA28MAX; case ATA_CMD_PIO_WRITE_EXT: lba &= 0x0000FFFFFFFFFFFFULL; rw = WRITE; } while (0); if ((lba + ata->scnt) > d->scnt) { printk(KERN_ERR "sector I/O is out of range: %Lu (%d), max %Lu\n", (long long) lba, ata->scnt, d->scnt); ata->cmdstat = ATA_ERR; ata->errfeat = ATA_IDNF; break; } rq = d->reqs; e = rq + nelem(d->reqs); for (; rq<e; rq++) if (rq->skb == NULL) break; if (rq == e) goto drop; bio = bio_alloc(GFP_ATOMIC, 1); if (bio == NULL) { eprintk("can't alloc bio\n"); goto drop; } rq->bio = bio; rq->d = d; bio->bi_sector = lba; bio->bi_bdev = d->blkdev; bio->bi_end_io = ata_io_complete; bio->bi_private = rq; page = virt_to_page(ata->data); bcnt = ata->scnt << 9; offset = offset_in_page(ata->data); if (bio_add_page(bio, page, bcnt, offset) < bcnt) { printk(KERN_ERR "Can't bio_add_page for %d sectors\n", ata->scnt); bio_put(bio); goto drop; } rq->skb = skb; atomic_inc(&d->busy); submit_bio(rw, bio); return NULL; default: printk(KERN_ERR "Unknown ATA command 0x%02X\n", ata->cmdstat); ata->cmdstat = ATA_ERR; ata->errfeat = ATA_ABORTED; break; case ATA_CMD_ID_ATA: len += ata_identify(d, ata); case ATA_CMD_FLUSH: ata->cmdstat = ATA_DRDY; ata->errfeat = 0; break; } skb_trim(skb, len); return skb; drop: dev_kfree_skb(skb); return NULL; }