Exemplo n.º 1
0
int ahci_write_prdt(struct hba_memory *abar, struct hba_port *port, struct ahci_device *dev, int slot, int offset, int length, addr_t virt_buffer)
{
	int num_entries = ((length-1) / PRDT_MAX_COUNT) + 1;
	struct hba_command_table *tbl = (struct hba_command_table *)(dev->ch[slot]);
	int i;
	struct hba_prdt_entry *prd;
	for(i=0;i<num_entries-1;i++)
	{
		/* TODO: do we need to do this? */
		addr_t phys_buffer;
		mm_virtual_getmap(virt_buffer, &phys_buffer, 0);
		prd = &tbl->prdt_entries[i+offset];
		prd->byte_count = PRDT_MAX_COUNT-1;
		prd->data_base_l = LOWER32(phys_buffer);
		prd->data_base_h = UPPER32(phys_buffer);
		prd->interrupt_on_complete=0;
		
		length -= PRDT_MAX_COUNT;
		virt_buffer += PRDT_MAX_COUNT;
	}
	addr_t phys_buffer;
	mm_virtual_getmap(virt_buffer, &phys_buffer, 0);
	prd = &tbl->prdt_entries[i+offset];
	prd->byte_count = length-1;
	prd->data_base_l = LOWER32(phys_buffer);
	prd->data_base_h = UPPER32(phys_buffer);
	prd->interrupt_on_complete=0;
	
	return num_entries;
}
Exemplo n.º 2
0
/* Decrease the count of each requested page by 1, and unmap it from the virtual address.
 * If the count reaches zero, sync the page, free it, and delete the entry to the hash table. */
void fs_inode_unmap_region(struct inode *node, addr_t virt, size_t offset, size_t length)
{
	mutex_acquire(&node->mappings_lock);
	ASSERT(node->flags & INODE_PCACHE);
	ASSERT(!(offset & ~PAGE_MASK));
	ASSERT(!(virt & ~PAGE_MASK));
	int page_number = offset / PAGE_SIZE;
	int npages = ((length-1) / PAGE_SIZE) + 1;
	for(int i = page_number; i < (page_number + npages); i++)
	{
		struct physical_page *entry;
		if((entry = hash_lookup(&node->physicals, &i, sizeof(i))) != NULL) {
			mutex_acquire(&entry->lock);
			atomic_fetch_sub(&entry->count, 1);
			mutex_release(&entry->lock);
		}
		// We'll actually do the unmapping too.
		int attr;
		addr_t page;
		if(mm_virtual_getmap(virt + (i - page_number)*PAGE_SIZE, &page, &attr)) {
			mm_virtual_unmap(virt + (i - page_number)*PAGE_SIZE);
			mm_physical_decrement_count(entry->page);
		}
	}
	mutex_release(&node->mappings_lock);
}
Exemplo n.º 3
0
void fs_inode_sync_physical_page(struct inode *node, addr_t virt, size_t offset, size_t req_len)
{
	ASSERT(!(offset & ~PAGE_MASK));
	ASSERT(!(virt & ~PAGE_MASK));
	if(!mm_virtual_getmap(virt, NULL, NULL))
		return;
	// Again, no real good way to notify userspace of a failure.
	size_t len = req_len;
	if(len + offset > (size_t)node->length)
		len = node->length - offset;
	if(offset >= (size_t)node->length)
		return;
	if(node->filesystem && fs_inode_write(node, offset, len, (void *)virt) < 0)
		printk(0, "[MMINODE]: WARNING: Failed to write back data.\n");
}