Exemple #1
0
/** Copy the contents of a page.
 * @param dest		Destination page.
 * @param source	Source page.
 * @param mmflag	Allocation flags for mapping page in memory.
 * @return		True if successful, false if unable to map pages into
 *			memory (cannot happen if MM_WAIT is specified). */
bool phys_copy(phys_ptr_t dest, phys_ptr_t source, unsigned mmflag) {
	void *mdest, *msrc;

	assert(!(dest % PAGE_SIZE));
	assert(!(source % PAGE_SIZE));

	preempt_disable();

	mdest = phys_map(dest, PAGE_SIZE, mmflag);
	if(unlikely(!mdest)) {
		preempt_enable();
		return false;
	}

	msrc = phys_map(source, PAGE_SIZE, mmflag);
	if(unlikely(!msrc)) {
		phys_unmap(mdest, PAGE_SIZE, false);
		preempt_enable();
		return false;
	}

	memcpy(mdest, msrc, PAGE_SIZE);
	phys_unmap(msrc, PAGE_SIZE, false);
	phys_unmap(mdest, PAGE_SIZE, false);
	preempt_enable();
	return true;
}
Exemple #2
0
/** Dump a sections tag. */
static void dump_sections_tag(kboot_tag_sections_t *tag) {
    const char *strtab;
    elf_shdr_t *shdr;

    printf("KBOOT_TAG_SECTIONS:\n");
    printf("  num      = %" PRIu32 "\n", tag->num);
    printf("  entsize  = %" PRIu32 "\n", tag->entsize);
    printf("  shstrndx = %" PRIu32 "\n", tag->shstrndx);

    shdr = get_elf_section(tag, tag->shstrndx);
    strtab = phys_map(shdr->sh_addr, round_up(shdr->sh_size, PAGE_SIZE));
    printf("  shstrtab = 0x%lx (%p)\n", shdr->sh_addr, strtab);

    for (uint32_t i = 0; i < tag->num; i++) {
        shdr = get_elf_section(tag, i);

        printf("  section %u (`%s'):\n", i, (shdr->sh_name) ? strtab + shdr->sh_name : "");
        printf("    sh_type  = %" PRIu32 "\n", shdr->sh_type);
        printf("    sh_flags = 0x%" PRIx32 "\n", shdr->sh_flags);
        printf("    sh_addr  = %p\n", shdr->sh_addr);
        printf("    sh_size  = %" PRIu32 "\n", shdr->sh_size);
    }
}
Exemple #3
0
/** Register a new PCI ATA channel.
 * @param pci_device	PCI device the channel is on.
 * @param idx		Channel index.
 * @param ctrl_base	Control registers base address.
 * @param cmd_base	Command registers base address.
 * @param bm_base	Bus master base address.
 * @param irq		IRQ number.
 * @return		Pointer to ATA channel structure if present. */
static ata_channel_t *pci_ata_channel_add(pci_device_t *pci_device, int idx, uint32_t ctrl_base,
                                          uint32_t cmd_base, uint32_t bm_base, uint32_t irq) {
	uint16_t pci_cmd_old, pci_cmd_new;
	pci_ata_channel_t *channel;
	bool dma = true;
	status_t ret;

	/* Configure the PCI device appropriately. */
	pci_cmd_old = pci_cmd_new = pci_config_read16(pci_device, PCI_CONFIG_COMMAND);
	pci_cmd_new &= ~PCI_COMMAND_INT_DISABLE;
	pci_cmd_new |= (PCI_COMMAND_IO | PCI_COMMAND_BUS_MASTER);
	if(pci_cmd_new != pci_cmd_old) {
		pci_config_write16(pci_device, PCI_CONFIG_COMMAND, pci_cmd_new);
		kprintf(LOG_DEBUG, "ata: reconfigured PCI device %d:%02x.%d (old: 0x%04x, new: 0x%04x)\n",
		        pci_device->bus, pci_device->device, pci_device->function,
		        pci_cmd_old, pci_cmd_new);
        }

	/* Check presence by writing a value to the low LBA port on the channel,
	 * then reading it back. If the value is the same, it is present. */
	out8(cmd_base + ATA_CMD_REG_LBA_LOW, 0xAB);
	if(in8(cmd_base + ATA_CMD_REG_LBA_LOW) != 0xAB) {
		if(pci_cmd_new != pci_cmd_old) {
			pci_config_write16(pci_device, PCI_CONFIG_COMMAND, pci_cmd_old);
		}
		return NULL;
	}

	/* Allocate our information structure. */
	channel = kmalloc(sizeof(*channel), MM_WAIT);
	channel->channel = NULL;
	channel->pci_device = pci_device;
	channel->ctrl_base = ctrl_base;
	channel->cmd_base = cmd_base;
	channel->bus_master_base = bm_base + (idx * 8);
	channel->irq = irq;
	channel->prdt = NULL;

	/* If the bus master is in simplex mode, disable DMA on the second
	 * channel. According to the Haiku code, Intel controllers use this for
	 * something other than simplex mode. */
	if(pci_device->vendor_id != 0x8086) {
		if(in8(bm_base + PCI_ATA_BM_REG_STATUS) & PCI_ATA_BM_STATUS_SIMPLEX && idx > 1) {
			dma = false;
		}
	}

	/* Allocate a PRDT if necessary. */
	if(dma) {
		phys_alloc(PRDT_SIZE, 0, 0, 0, (phys_ptr_t)0x100000000, MM_WAIT, &channel->prdt_phys);
		channel->prdt = phys_map(channel->prdt_phys, PRDT_SIZE, MM_WAIT);
	}

	/* Register the IRQ handler. */
	ret = irq_register(channel->irq, pci_ata_irq_handler, NULL, channel);
	if(ret != STATUS_SUCCESS) {
		kprintf(LOG_WARN, "ata: failed to register PCI ATA IRQ handler %u\n", channel->irq);
		if(dma) {
			phys_unmap(channel->prdt, PRDT_SIZE, true);
			phys_free(channel->prdt_phys, PRDT_SIZE);
		}
		kfree(channel);
		return NULL;
	}

	/* Try to register the ATA channel. */
	channel->channel = ata_sff_channel_add(pci_device->node, idx, &pci_ata_channel_ops, channel,
	                                       dma, PRDT_ENTRIES, (phys_ptr_t)0x100000000);
	if(!channel->channel) {
		irq_unregister(channel->irq, pci_ata_irq_handler, NULL, channel);
		if(dma) {
			phys_unmap(channel->prdt, PRDT_SIZE, true);
			phys_free(channel->prdt_phys, PRDT_SIZE);
		}
		kfree(channel);
		return NULL;
	}

	return channel->channel;
}