the simplest memory manager & index buffers

git-svn-id: svn://kolibrios.org@1120 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2009-07-02 17:11:39 +00:00
parent e92d5a0b39
commit c9b2d4590c
16 changed files with 3798 additions and 394 deletions

View File

@ -0,0 +1,105 @@
/**************************************************************************
*
* Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX. USA.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
**************************************************************************/
/*
* Authors:
* Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
*/
#ifndef _DRM_MM_H_
#define _DRM_MM_H_
/*
* Generic range manager structs
*/
#include <types.h>
#include <list.h>
#include <errno-base.h>
#define spin_lock_init(x)
#define spin_lock(x)
#define spin_unlock(x)
struct drm_mm_node {
struct list_head fl_entry;
struct list_head ml_entry;
int free;
unsigned long start;
unsigned long size;
struct drm_mm *mm;
void *private;
};
struct drm_mm {
struct list_head fl_entry;
struct list_head ml_entry;
struct list_head unused_nodes;
int num_unused;
// spinlock_t unused_lock;
};
/*
* Basic range manager support (drm_mm.c)
*/
extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
unsigned long size,
unsigned alignment,
int atomic);
static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent,
unsigned long size,
unsigned alignment)
{
return drm_mm_get_block_generic(parent, size, alignment, 0);
}
static inline struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent,
unsigned long size,
unsigned alignment)
{
return drm_mm_get_block_generic(parent, size, alignment, 1);
}
extern void drm_mm_put_block(struct drm_mm_node *cur);
extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
unsigned long size,
unsigned alignment,
int best_match);
extern int drm_mm_init(struct drm_mm *mm, unsigned long start,
unsigned long size);
extern void drm_mm_takedown(struct drm_mm *mm);
extern int drm_mm_clean(struct drm_mm *mm);
extern unsigned long drm_mm_tail_space(struct drm_mm *mm);
extern int drm_mm_remove_space_from_tail(struct drm_mm *mm,
unsigned long size);
extern int drm_mm_add_space_to_tail(struct drm_mm *mm,
unsigned long size, int atomic);
extern int drm_mm_pre_get(struct drm_mm *mm);
static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block)
{
return block->mm;
}
#endif

View File

@ -0,0 +1,703 @@
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H
//#include <linux/stddef.h>
//#include <linux/poison.h>
//#include <linux/prefetch.h>
//#include <asm/system.h>
/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
#define LIST_POISON1 ((struct list_head*)0xFFFF0100)
#define LIST_POISON2 ((struct list_head*)0xFFFF0200)
#define prefetch(x) __builtin_prefetch(x)
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
#ifndef CONFIG_DEBUG_LIST
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
#else
extern void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next);
#endif
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
#ifndef CONFIG_DEBUG_LIST
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
#else
extern void list_del(struct list_head *entry);
#endif
/**
* list_replace - replace old entry by new one
* @old : the element to be replaced
* @new : the new element to insert
*
* If @old was empty, it will be overwritten.
*/
static inline void list_replace(struct list_head *old,
struct list_head *new)
{
new->next = old->next;
new->next->prev = new;
new->prev = old->prev;
new->prev->next = new;
}
static inline void list_replace_init(struct list_head *old,
struct list_head *new)
{
list_replace(old, new);
INIT_LIST_HEAD(old);
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del(list->prev, list->next);
list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del(list->prev, list->next);
list_add_tail(list, head);
}
/**
* list_is_last - tests whether @list is the last entry in list @head
* @list: the entry to test
* @head: the head of the list
*/
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
/**
* list_empty_careful - tests whether a list is empty and not being modified
* @head: the list to test
*
* Description:
* tests whether a list is empty _and_ checks that no other CPU might be
* in the process of modifying either member (next or prev)
*
* NOTE: using list_empty_careful() without synchronization
* can only be safe if the only activity that can happen
* to the list entry is list_del_init(). Eg. it cannot be used
* if another CPU could re-list_add() it.
*/
static inline int list_empty_careful(const struct list_head *head)
{
struct list_head *next = head->next;
return (next == head) && (next == head->prev);
}
/**
* list_is_singular - tests whether a list has just one entry.
* @head: the list to test.
*/
static inline int list_is_singular(const struct list_head *head)
{
return !list_empty(head) && (head->next == head->prev);
}
static inline void __list_cut_position(struct list_head *list,
struct list_head *head, struct list_head *entry)
{
struct list_head *new_first = entry->next;
list->next = head->next;
list->next->prev = list;
list->prev = entry;
entry->next = list;
head->next = new_first;
new_first->prev = head;
}
/**
* list_cut_position - cut a list into two
* @list: a new list to add all removed entries
* @head: a list with entries
* @entry: an entry within head, could be the head itself
* and if so we won't cut the list
*
* This helper moves the initial part of @head, up to and
* including @entry, from @head to @list. You should
* pass on @entry an element you know is on @head. @list
* should be an empty list or a list you do not care about
* losing its data.
*
*/
static inline void list_cut_position(struct list_head *list,
struct list_head *head, struct list_head *entry)
{
if (list_empty(head))
return;
if (list_is_singular(head) &&
(head->next != entry && head != entry))
return;
if (entry == head)
INIT_LIST_HEAD(list);
else
__list_cut_position(list, head, entry);
}
static inline void __list_splice(const struct list_head *list,
struct list_head *prev,
struct list_head *next)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
first->prev = prev;
prev->next = first;
last->next = next;
next->prev = last;
}
/**
* list_splice - join two lists, this is designed for stacks
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(const struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head, head->next);
}
/**
* list_splice_tail - join two lists, each list being a queue
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice_tail(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head->prev, head);
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head, head->next);
INIT_LIST_HEAD(list);
}
}
/**
* list_splice_tail_init - join two lists and reinitialise the emptied list
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* Each of the lists is a queue.
* The list at @list is reinitialised
*/
static inline void list_splice_tail_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head->prev, head);
INIT_LIST_HEAD(list);
}
}
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/**
* list_first_entry - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
pos = pos->next)
/**
* __list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*
* This variant differs from list_for_each() in that it's the
* simplest possible list iteration code, no prefetching is done.
* Use this for code that knows the list to be very short (empty
* or 1 entry) most of the time.
*/
#define __list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_prev_safe(pos, n, head) \
for (pos = (head)->prev, n = pos->prev; \
prefetch(pos->prev), pos != (head); \
pos = n, n = pos->prev)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_reverse(pos, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member); \
prefetch(pos->member.prev), &pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
* @pos: the type * to use as a start point
* @head: the head of the list
* @member: the name of the list_struct within the struct.
*
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
*/
#define list_prepare_entry(pos, head, member) \
((pos) ? : list_entry(head, typeof(*pos), member))
/**
* list_for_each_entry_continue - continue iteration over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Continue to iterate over list of given type, continuing after
* the current position.
*/
#define list_for_each_entry_continue(pos, head, member) \
for (pos = list_entry(pos->member.next, typeof(*pos), member); \
prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_continue_reverse - iterate backwards from the given point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Start to iterate over list of given type backwards, continuing after
* the current position.
*/
#define list_for_each_entry_continue_reverse(pos, head, member) \
for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
prefetch(pos->member.prev), &pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
* list_for_each_entry_from - iterate over list of given type from the current point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing from current position.
*/
#define list_for_each_entry_from(pos, head, member) \
for (; prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_continue
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
*/
#define list_for_each_entry_safe_continue(pos, n, head, member) \
for (pos = list_entry(pos->member.next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_from
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
*/
#define list_for_each_entry_safe_from(pos, n, head, member) \
for (n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_reverse
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
*/
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member), \
n = list_entry(pos->member.prev, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
/*
* Double linked lists with a single pointer list head.
* Mostly useful for hash tables where the two pointer list head is
* too wasteful.
* You lose the ability to access the tail in O(1).
*/
#if 0
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
h->next = NULL;
h->pprev = NULL;
}
static inline int hlist_unhashed(const struct hlist_node *h)
{
return !h->pprev;
}
static inline int hlist_empty(const struct hlist_head *h)
{
return !h->first;
}
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
struct hlist_node **pprev = n->pprev;
*pprev = next;
if (next)
next->pprev = pprev;
}
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
n->next = LIST_POISON1;
n->pprev = LIST_POISON2;
}
static inline void hlist_del_init(struct hlist_node *n)
{
if (!hlist_unhashed(n)) {
__hlist_del(n);
INIT_HLIST_NODE(n);
}
}
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
n->next = first;
if (first)
first->pprev = &n->next;
h->first = n;
n->pprev = &h->first;
}
/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
struct hlist_node *next)
{
n->pprev = next->pprev;
n->next = next;
next->pprev = &n->next;
*(n->pprev) = n;
}
static inline void hlist_add_after(struct hlist_node *n,
struct hlist_node *next)
{
next->next = n->next;
n->next = next;
next->pprev = &n->next;
if(next->next)
next->next->pprev = &next->next;
}
/*
* Move a list from one list head to another. Fixup the pprev
* reference of the first entry if it exists.
*/
static inline void hlist_move_list(struct hlist_head *old,
struct hlist_head *new)
{
new->first = old->first;
if (new->first)
new->first->pprev = &new->first;
old->first = NULL;
}
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
pos = n)
/**
* hlist_for_each_entry - iterate over list of given type
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry(tpos, pos, head, member) \
for (pos = (head)->first; \
pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_continue(tpos, pos, member) \
for (pos = (pos)->next; \
pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_from(tpos, pos, member) \
for (; pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @n: another &struct hlist_node to use as temporary storage
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
for (pos = (head)->first; \
pos && ({ n = pos->next; 1; }) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = n)
#endif
#endif

View File

@ -1165,7 +1165,7 @@ struct atom_context *atom_parse(struct card_info *card, void *bios)
int atom_asic_init(struct atom_context *ctx)
{
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
int hwi = CU16(ctx->data_table + ATOM_DATA_FWI_PTR);
uint32_t ps[16];

View File

@ -3,7 +3,7 @@
#include <errno-base.h>
#include <syscall.h>
link_t devices;
static LIST_HEAD(devices);
static dev_t* pci_scan_device(u32_t bus, int devfn);
@ -346,7 +346,7 @@ static dev_t* pci_scan_device(u32_t bus, int devfn)
dev = (dev_t*)malloc(sizeof(dev_t));
link_initialize(&dev->link);
INIT_LIST_HEAD(&dev->link);
if(unlikely(dev == NULL))
return NULL;
@ -375,7 +375,7 @@ int pci_scan_slot(u32_t bus, int devfn)
dev = pci_scan_device(bus, devfn);
if( dev )
{
list_append(&dev->link, &devices);
list_add(&dev->link, &devices);
nr++;
@ -420,7 +420,7 @@ int enum_pci_devices()
u32_t last_bus;
u32_t bus = 0 , devfn = 0;
list_initialize(&devices);
// list_initialize(&devices);
last_bus = PciApi(1);

View File

@ -268,6 +268,7 @@ void r100_fence_ring_emit(struct radeon_device *rdev,
radeon_ring_write(rdev, RADEON_SW_INT_FIRE);
}
#endif
/*
* Writeback
@ -307,14 +308,16 @@ int r100_wb_init(struct radeon_device *rdev)
void r100_wb_fini(struct radeon_device *rdev)
{
if (rdev->wb.wb_obj) {
radeon_object_kunmap(rdev->wb.wb_obj);
radeon_object_unpin(rdev->wb.wb_obj);
radeon_object_unref(&rdev->wb.wb_obj);
// radeon_object_kunmap(rdev->wb.wb_obj);
// radeon_object_unpin(rdev->wb.wb_obj);
// radeon_object_unref(&rdev->wb.wb_obj);
rdev->wb.wb = NULL;
rdev->wb.wb_obj = NULL;
}
}
#if 0
int r100_copy_blit(struct radeon_device *rdev,
uint64_t src_offset,
uint64_t dst_offset,
@ -415,7 +418,7 @@ static void r100_cp_load_microcode(struct radeon_device *rdev)
{
int i;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
if (r100_gui_wait_for_idle(rdev)) {
printk(KERN_WARNING "Failed to wait GUI idle while "
@ -498,7 +501,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
uint32_t tmp;
int r;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
// if (r100_debugfs_cp_init(rdev)) {
// DRM_ERROR("Failed to register debugfs file for CP !\n");
@ -624,7 +627,7 @@ int r100_cp_reset(struct radeon_device *rdev)
bool reinit_cp;
int i;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
reinit_cp = rdev->cp.ready;
@ -1170,7 +1173,7 @@ void r100_hdp_reset(struct radeon_device *rdev)
{
uint32_t tmp;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL;
tmp |= (7 << 28);
@ -1187,7 +1190,7 @@ int r100_rb2d_reset(struct radeon_device *rdev)
uint32_t tmp;
int i;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_E2);
(void)RREG32(RADEON_RBBM_SOFT_RESET);

File diff suppressed because it is too large Load Diff

View File

@ -155,7 +155,7 @@ int r520_mc_wait_for_idle(struct radeon_device *rdev)
void r520_gpu_init(struct radeon_device *rdev)
{
unsigned pipe_select_current, gb_pipe_select, tmp;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
r100_hdp_reset(rdev);
rs600_disable_vga(rdev);
@ -204,7 +204,7 @@ void r520_gpu_init(struct radeon_device *rdev)
static void r520_vram_get_type(struct radeon_device *rdev)
{
uint32_t tmp;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
rdev->mc.vram_width = 128;
rdev->mc.vram_is_ddr = true;
@ -245,7 +245,7 @@ void r520_vram_info(struct radeon_device *rdev)
void rs600_disable_vga(struct radeon_device *rdev)
{
unsigned tmp;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
WREG32(0x330, 0);
WREG32(0x338, 0);
@ -264,7 +264,7 @@ void r420_pipes_init(struct radeon_device *rdev)
unsigned gb_pipe_select;
unsigned num_pipes;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
/* GA_ENHANCE workaround TCL deadlock issue */
WREG32(0x4274, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3));
@ -314,83 +314,11 @@ void r420_pipes_init(struct radeon_device *rdev)
DRM_INFO("radeon: %d pipes initialized.\n", rdev->num_gb_pipes);
}
void rv370_pcie_gart_disable(struct radeon_device *rdev)
{
uint32_t tmp;
dbgprintf("%s\n\r",__FUNCTION__);
tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN);
if (rdev->gart.table.vram.robj) {
// radeon_object_kunmap(rdev->gart.table.vram.robj);
// radeon_object_unpin(rdev->gart.table.vram.robj);
}
}
void radeon_gart_table_vram_free(struct radeon_device *rdev)
{
if (rdev->gart.table.vram.robj == NULL) {
return;
}
// radeon_object_kunmap(rdev->gart.table.vram.robj);
// radeon_object_unpin(rdev->gart.table.vram.robj);
// radeon_object_unref(&rdev->gart.table.vram.robj);
}
/*
* Common gart functions.
*/
void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
int pages)
{
unsigned t;
unsigned p;
int i, j;
dbgprintf("%s\n\r",__FUNCTION__);
if (!rdev->gart.ready) {
dbgprintf("trying to unbind memory to unitialized GART !\n");
return;
}
t = offset / 4096;
p = t / (PAGE_SIZE / 4096);
for (i = 0; i < pages; i++, p++) {
if (rdev->gart.pages[p]) {
// pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p],
// PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
rdev->gart.pages[p] = NULL;
rdev->gart.pages_addr[p] = 0;
for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) {
radeon_gart_set_page(rdev, t, 0);
}
}
}
mb();
radeon_gart_tlb_flush(rdev);
}
void radeon_gart_fini(struct radeon_device *rdev)
{
if (rdev->gart.pages && rdev->gart.pages_addr && rdev->gart.ready) {
/* unbind pages */
radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages);
}
rdev->gart.ready = false;
// kfree(rdev->gart.pages);
// kfree(rdev->gart.pages_addr);
rdev->gart.pages = NULL;
rdev->gart.pages_addr = NULL;
}
int radeon_agp_init(struct radeon_device *rdev)
{
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
#if __OS_HAS_AGP
struct radeon_agpmode_quirk *p = radeon_agpmode_quirk_list;
@ -535,182 +463,11 @@ void rs600_mc_disable_clients(struct radeon_device *rdev)
}
int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
{
void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
if (i < 0 || i > rdev->gart.num_gpu_pages) {
return -EINVAL;
}
addr = (((u32_t)addr) >> 8) | ((upper_32_bits(addr) & 0xff) << 4) | 0xC;
writel(cpu_to_le32(addr), ((void __iomem *)ptr) + (i * 4));
return 0;
}
int radeon_gart_init(struct radeon_device *rdev)
{
dbgprintf("%s\n",__FUNCTION__);
if (rdev->gart.pages) {
return 0;
}
/* We need PAGE_SIZE >= 4096 */
if (PAGE_SIZE < 4096) {
DRM_ERROR("Page size is smaller than GPU page size!\n");
return -EINVAL;
}
/* Compute table size */
rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE;
rdev->gart.num_gpu_pages = rdev->mc.gtt_size / 4096;
DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",
rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages);
/* Allocate pages table */
rdev->gart.pages = kzalloc(sizeof(void *) * rdev->gart.num_cpu_pages,
GFP_KERNEL);
if (rdev->gart.pages == NULL) {
// radeon_gart_fini(rdev);
return -ENOMEM;
}
rdev->gart.pages_addr = kzalloc(sizeof(u32_t) *
rdev->gart.num_cpu_pages, GFP_KERNEL);
if (rdev->gart.pages_addr == NULL) {
// radeon_gart_fini(rdev);
return -ENOMEM;
}
return 0;
}
int radeon_gart_table_vram_alloc(struct radeon_device *rdev)
{
uint32_t gpu_addr;
int r;
// if (rdev->gart.table.vram.robj == NULL) {
// r = radeon_object_create(rdev, NULL,
// rdev->gart.table_size,
// true,
// RADEON_GEM_DOMAIN_VRAM,
// false, &rdev->gart.table.vram.robj);
// if (r) {
// return r;
// }
// }
// r = radeon_object_pin(rdev->gart.table.vram.robj,
// RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
// if (r) {
// radeon_object_unref(&rdev->gart.table.vram.robj);
// return r;
// }
// r = radeon_object_kmap(rdev->gart.table.vram.robj,
// (void **)&rdev->gart.table.vram.ptr);
// if (r) {
// radeon_object_unpin(rdev->gart.table.vram.robj);
// radeon_object_unref(&rdev->gart.table.vram.robj);
// DRM_ERROR("radeon: failed to map gart vram table.\n");
// return r;
// }
gpu_addr = 0x800000;
u32_t pci_addr = rdev->mc.aper_base + gpu_addr;
rdev->gart.table.vram.ptr = (void*)MapIoMem(pci_addr, rdev->gart.table_size, PG_SW);
rdev->gart.table_addr = gpu_addr;
dbgprintf("alloc gart vram:\n gpu_base %x pci_base %x lin_addr %x",
gpu_addr, pci_addr, rdev->gart.table.vram.ptr);
return 0;
}
void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev);
int rv370_pcie_gart_enable(struct radeon_device *rdev)
{
uint32_t table_addr;
uint32_t tmp;
int r;
dbgprintf("%s\n",__FUNCTION__);
/* Initialize common gart structure */
r = radeon_gart_init(rdev);
if (r) {
return r;
}
// r = rv370_debugfs_pcie_gart_info_init(rdev);
// if (r) {
// DRM_ERROR("Failed to register debugfs file for PCIE gart !\n");
// }
rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
r = radeon_gart_table_vram_alloc(rdev);
if (r) {
return r;
}
/* discard memory request outside of configured range */
tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_location);
tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 4096;
WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, tmp);
WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0);
WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0);
table_addr = rdev->gart.table_addr;
WREG32_PCIE(RADEON_PCIE_TX_GART_BASE, table_addr);
/* FIXME: setup default page */
WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_location);
WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_HI, 0);
/* Clear error */
WREG32_PCIE(0x18, 0);
tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
tmp |= RADEON_PCIE_TX_GART_EN;
tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
rv370_pcie_gart_tlb_flush(rdev);
DRM_INFO("PCIE GART of %uM enabled (table at 0x%08X).\n",
rdev->mc.gtt_size >> 20, table_addr);
rdev->gart.ready = true;
return 0;
}
void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev)
{
uint32_t tmp;
int i;
/* Workaround HW bug do flush 2 times */
for (i = 0; i < 2; i++) {
tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp | RADEON_PCIE_TX_GART_INVALIDATE_TLB);
(void)RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
mb();
}
}
int r300_gart_enable(struct radeon_device *rdev)
{
#if __OS_HAS_AGP
if (rdev->flags & RADEON_IS_AGP) {
if (rdev->family > CHIP_RV350) {
rv370_pcie_gart_disable(rdev);
} else {
r100_pci_gart_disable(rdev);
}
return 0;
}
#endif
if (rdev->flags & RADEON_IS_PCIE) {
rdev->asic->gart_disable = &rv370_pcie_gart_disable;
rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
return rv370_pcie_gart_enable(rdev);
}
// return r100_pci_gart_enable(rdev);
}
@ -741,49 +498,7 @@ int radeon_fence_driver_init(struct radeon_device *rdev)
}
int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
int pages, u32_t *pagelist)
{
unsigned t;
unsigned p;
uint64_t page_base;
int i, j;
dbgprintf("%s\n\r",__FUNCTION__);
if (!rdev->gart.ready) {
DRM_ERROR("trying to bind memory to unitialized GART !\n");
return -EINVAL;
}
t = offset / 4096;
p = t / (PAGE_SIZE / 4096);
for (i = 0; i < pages; i++, p++) {
/* we need to support large memory configurations */
/* assume that unbind have already been call on the range */
rdev->gart.pages_addr[p] = pagelist[i] & ~4095;
//if (pci_dma_mapping_error(rdev->pdev, rdev->gart.pages_addr[p])) {
// /* FIXME: failed to map page (return -ENOMEM?) */
// radeon_gart_unbind(rdev, offset, pages);
// return -ENOMEM;
//}
rdev->gart.pages[p] = pagelist[i];
page_base = (uint32_t)rdev->gart.pages_addr[p];
for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) {
radeon_gart_set_page(rdev, t, page_base);
page_base += 4096;
}
}
mb();
radeon_gart_tlb_flush(rdev);
dbgprintf("done %s\n",__FUNCTION__);
return 0;
}

View File

@ -44,10 +44,12 @@
* - TESTING, TESTING, TESTING
*/
#include "types.h"
#include "pci.h"
#include <types.h>
#include <list.h>
#include "errno-base.h"
#include <pci.h>
#include <errno-base.h>
#include "radeon_mode.h"
#include "radeon_reg.h"
@ -60,15 +62,14 @@ extern int radeon_gart_size;
extern int radeon_r4xx_atom;
/*
* Copy from radeon_drv.h so we don't have to include both and have conflicting
* symbol;
*/
#define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */
#define RADEON_IB_POOL_SIZE 16
#define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */
#define RADEON_IB_POOL_SIZE 16
#define RADEON_DEBUGFS_MAX_NUM_FILES 32
#define RADEONFB_CONN_LIMIT 4
#define RADEONFB_CONN_LIMIT 4
enum radeon_family {
CHIP_R100,
@ -169,15 +170,15 @@ struct radeon_fence_driver {
unsigned long count_timeout;
// wait_queue_head_t queue;
// rwlock_t lock;
// struct list_head created;
// struct list_head emited;
// struct list_head signaled;
struct list_head created;
struct list_head emited;
struct list_head signaled;
};
struct radeon_fence {
struct radeon_device *rdev;
// struct kref kref;
// struct list_head list;
struct list_head list;
/* protected by radeon_fence.lock */
uint32_t seq;
unsigned long timeout;
@ -204,7 +205,7 @@ void radeon_fence_unref(struct radeon_fence **fence);
struct radeon_object;
struct radeon_object_list {
// struct list_head list;
struct list_head list;
struct radeon_object *robj;
uint64_t gpu_offset;
unsigned rdomain;
@ -216,7 +217,6 @@ struct radeon_object_list {
/*
* GART structures, functions & helpers
*/
@ -255,8 +255,8 @@ int radeon_gart_init(struct radeon_device *rdev);
void radeon_gart_fini(struct radeon_device *rdev);
void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
int pages);
//int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
// int pages, struct page **pagelist);
int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
int pages, u32_t *pagelist);
/*
@ -309,7 +309,7 @@ void radeon_irq_kms_fini(struct radeon_device *rdev);
* CP & ring.
*/
struct radeon_ib {
// struct list_head list;
struct list_head list;
unsigned long idx;
uint64_t gpu_addr;
struct radeon_fence *fence;
@ -320,10 +320,10 @@ struct radeon_ib {
struct radeon_ib_pool {
// struct mutex mutex;
struct radeon_object *robj;
// struct list_head scheduled_ibs;
struct list_head scheduled_ibs;
struct radeon_ib ibs[RADEON_IB_POOL_SIZE];
bool ready;
// DECLARE_BITMAP(alloc_bm, RADEON_IB_POOL_SIZE);
DECLARE_BITMAP(alloc_bm, RADEON_IB_POOL_SIZE);
};
struct radeon_cp {
@ -364,7 +364,7 @@ void radeon_ring_fini(struct radeon_device *rdev);
struct radeon_cs_reloc {
// struct drm_gem_object *gobj;
struct radeon_object *robj;
// struct radeon_object_list lobj;
struct radeon_object_list lobj;
uint32_t handle;
uint32_t flags;
};
@ -388,7 +388,7 @@ struct radeon_cs_parser {
unsigned nrelocs;
struct radeon_cs_reloc *relocs;
struct radeon_cs_reloc **relocs_ptr;
// struct list_head validated;
struct list_head validated;
/* indices of various chunks */
int chunk_ib_idx;
int chunk_relocs_idx;
@ -512,24 +512,24 @@ struct radeon_device {
unsigned long rmmio_size;
void *rmmio;
radeon_rreg_t mm_rreg;
radeon_wreg_t mm_wreg;
radeon_rreg_t mc_rreg;
radeon_wreg_t mc_wreg;
radeon_rreg_t pll_rreg;
radeon_wreg_t pll_wreg;
radeon_rreg_t pcie_rreg;
radeon_wreg_t pcie_wreg;
radeon_rreg_t pciep_rreg;
radeon_wreg_t pciep_wreg;
struct radeon_clock clock;
radeon_rreg_t mm_rreg;
radeon_wreg_t mm_wreg;
radeon_rreg_t mc_rreg;
radeon_wreg_t mc_wreg;
radeon_rreg_t pll_rreg;
radeon_wreg_t pll_wreg;
radeon_rreg_t pcie_rreg;
radeon_wreg_t pcie_wreg;
radeon_rreg_t pciep_rreg;
radeon_wreg_t pciep_wreg;
struct radeon_clock clock;
struct radeon_mc mc;
struct radeon_gart gart;
struct radeon_mode_info mode_info;
struct radeon_scratch scratch;
// struct radeon_mman mman;
// struct radeon_mman mman;
struct radeon_fence_driver fence_drv;
struct radeon_cp cp;
struct radeon_cp cp;
struct radeon_ib_pool ib_pool;
// struct radeon_irq irq;
struct radeon_asic *asic;

View File

@ -403,8 +403,8 @@ static struct radeon_asic r520_asic = {
.gpu_reset = &rv515_gpu_reset,
.mc_init = &r520_mc_init,
.mc_fini = &r520_mc_fini,
// .wb_init = &r100_wb_init,
// .wb_fini = &r100_wb_fini,
.wb_init = &r100_wb_init,
.wb_fini = &r100_wb_fini,
.gart_enable = &r300_gart_enable,
.gart_disable = &rv370_pcie_gart_disable,
.gart_tlb_flush = &rv370_pcie_gart_tlb_flush,

View File

@ -944,7 +944,7 @@ void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
struct radeon_device *rdev = dev->dev_private;
uint32_t bios_2_scratch, bios_6_scratch;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
if (rdev->family >= CHIP_R600) {
bios_2_scratch = RREG32(R600_BIOS_0_SCRATCH);

View File

@ -39,7 +39,7 @@ static bool radeon_read_bios(struct radeon_device *rdev)
size_t size;
rdev->bios = NULL;
bios = pci_map_rom(rdev->pdev, &size);
bios = (uint8_t*)pci_map_rom(rdev->pdev, &size);
if (!bios) {
return false;
}

View File

@ -46,7 +46,7 @@ int radeon_gart_size = 512; /* default gart size */
*/
static void radeon_surface_init(struct radeon_device *rdev)
{
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
/* FIXME: check this out */
if (rdev->family < CHIP_R600) {
@ -180,7 +180,7 @@ static bool radeon_card_posted(struct radeon_device *rdev)
{
uint32_t reg;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
/* first check CRTCs */
if (ASIC_IS_AVIVO(rdev)) {
@ -231,7 +231,7 @@ void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
void radeon_register_accessor_init(struct radeon_device *rdev)
{
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
rdev->mm_rreg = &r100_mm_rreg;
rdev->mm_wreg = &r100_mm_wreg;
@ -288,7 +288,7 @@ void radeon_register_accessor_init(struct radeon_device *rdev)
int radeon_asic_init(struct radeon_device *rdev)
{
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
radeon_register_accessor_init(rdev);
switch (rdev->family) {
@ -360,7 +360,7 @@ int radeon_clocks_init(struct radeon_device *rdev)
{
int r;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
radeon_get_clock_info(rdev->ddev);
r = radeon_static_clocks_init(rdev->ddev);
@ -436,7 +436,7 @@ static struct card_info atom_card_info = {
int radeon_atombios_init(struct radeon_device *rdev)
{
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
atom_card_info.dev = rdev->ddev;
rdev->mode_info.atom_context = atom_parse(&atom_card_info, rdev->bios);
@ -462,7 +462,6 @@ void radeon_combios_fini(struct radeon_device *rdev)
int radeon_modeset_init(struct radeon_device *rdev);
void radeon_modeset_fini(struct radeon_device *rdev);
void *ring_buffer;
/*
* Radeon device.
*/
@ -473,7 +472,7 @@ int radeon_device_init(struct radeon_device *rdev,
{
int r, ret = -1;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
DRM_INFO("radeon: Initializing kernel modesetting.\n");
rdev->shutdown = false;
@ -492,7 +491,6 @@ int radeon_device_init(struct radeon_device *rdev,
// mutex_init(&rdev->cp.mutex);
// rwlock_init(&rdev->fence_drv.lock);
ring_buffer = CreateRingBuffer( 1024*1024, PG_SW );
if (radeon_agpmode == -1) {
rdev->flags &= ~RADEON_IS_AGP;
@ -620,10 +618,10 @@ int radeon_device_init(struct radeon_device *rdev,
// return r;
// }
/* Memory manager */
// r = radeon_object_init(rdev);
// if (r) {
// return r;
// }
r = radeon_object_init(rdev);
if (r) {
return r;
}
/* Initialize GART (initialize after TTM so we can allocate
* memory through TTM but finalize after TTM) */
r = radeon_gart_enable(rdev);
@ -635,15 +633,14 @@ int radeon_device_init(struct radeon_device *rdev,
if (!r) {
r = radeon_cp_init(rdev, 1024 * 1024);
}
// if (!r) {
// r = radeon_wb_init(rdev);
// if (r) {
// DRM_ERROR("radeon: failled initializing WB (%d).\n", r);
// return r;
// }
// }
if (!r) {
r = radeon_wb_init(rdev);
if (r) {
DRM_ERROR("radeon: failled initializing WB (%d).\n", r);
return r;
}
}
#if 0
if (!r) {
r = radeon_ib_pool_init(rdev);
if (r) {
@ -651,6 +648,8 @@ int radeon_device_init(struct radeon_device *rdev,
return r;
}
}
#if 0
if (!r) {
r = radeon_ib_test(rdev);
if (r) {
@ -694,9 +693,9 @@ u32_t __stdcall drvEntry(int action)
if(action != 1)
return 0;
if(!dbg_open("/rd/1/drivers/atikms.log"))
if(!dbg_open("/hd0/2/atikms.log"))
{
printf("Can't open /rd/1/drivers/ati2d.log\nExit\n");
printf("Can't open /hd0/2/atikms.log\nExit\n");
return 0;
}
@ -793,9 +792,9 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
struct radeon_device *rdev;
int r;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
rdev = malloc(sizeof(struct radeon_device));
rdev = kzalloc(sizeof(struct radeon_device), GFP_KERNEL);
if (rdev == NULL) {
return -ENOMEM;
};
@ -825,7 +824,7 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent)
struct drm_device *dev;
int ret;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
dev = malloc(sizeof(*dev));
if (!dev)

View File

@ -0,0 +1,261 @@
/*
* Copyright 2008 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
* Copyright 2009 Jerome Glisse.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Dave Airlie
* Alex Deucher
* Jerome Glisse
*/
//#include "drmP.h"
#include "radeon_drm.h"
#include "radeon.h"
#include "radeon_reg.h"
#if 0
/*
* Common GART table functions.
*/
int radeon_gart_table_ram_alloc(struct radeon_device *rdev)
{
void *ptr;
ptr = pci_alloc_consistent(rdev->pdev, rdev->gart.table_size,
&rdev->gart.table_addr);
if (ptr == NULL) {
return -ENOMEM;
}
#ifdef CONFIG_X86
if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 ||
rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
set_memory_uc((unsigned long)ptr,
rdev->gart.table_size >> PAGE_SHIFT);
}
#endif
rdev->gart.table.ram.ptr = ptr;
memset((void *)rdev->gart.table.ram.ptr, 0, rdev->gart.table_size);
return 0;
}
void radeon_gart_table_ram_free(struct radeon_device *rdev)
{
if (rdev->gart.table.ram.ptr == NULL) {
return;
}
#ifdef CONFIG_X86
if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 ||
rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
set_memory_wb((unsigned long)rdev->gart.table.ram.ptr,
rdev->gart.table_size >> PAGE_SHIFT);
}
#endif
pci_free_consistent(rdev->pdev, rdev->gart.table_size,
(void *)rdev->gart.table.ram.ptr,
rdev->gart.table_addr);
rdev->gart.table.ram.ptr = NULL;
rdev->gart.table_addr = 0;
}
#endif
int radeon_gart_table_vram_alloc(struct radeon_device *rdev)
{
uint32_t gpu_addr;
int r;
if (rdev->gart.table.vram.robj == NULL) {
r = radeon_object_create(rdev, NULL,
rdev->gart.table_size,
true,
RADEON_GEM_DOMAIN_VRAM,
false, &rdev->gart.table.vram.robj);
if (r) {
return r;
}
}
r = radeon_object_pin(rdev->gart.table.vram.robj,
RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
if (r) {
// radeon_object_unref(&rdev->gart.table.vram.robj);
return r;
}
r = radeon_object_kmap(rdev->gart.table.vram.robj,
(void **)&rdev->gart.table.vram.ptr);
if (r) {
// radeon_object_unpin(rdev->gart.table.vram.robj);
// radeon_object_unref(&rdev->gart.table.vram.robj);
DRM_ERROR("radeon: failed to map gart vram table.\n");
return r;
}
rdev->gart.table_addr = gpu_addr;
dbgprintf("alloc gart vram: gpu_base %x lin_addr %x\n",
rdev->gart.table_addr, rdev->gart.table.vram.ptr);
// gpu_addr = 0x800000;
// u32_t pci_addr = rdev->mc.aper_base + gpu_addr;
// rdev->gart.table.vram.ptr = (void*)MapIoMem(pci_addr, rdev->gart.table_size, PG_SW);
// dbgprintf("alloc gart vram:\n gpu_base %x pci_base %x lin_addr %x",
// gpu_addr, pci_addr, rdev->gart.table.vram.ptr);
return 0;
}
void radeon_gart_table_vram_free(struct radeon_device *rdev)
{
if (rdev->gart.table.vram.robj == NULL) {
return;
}
// radeon_object_kunmap(rdev->gart.table.vram.robj);
// radeon_object_unpin(rdev->gart.table.vram.robj);
// radeon_object_unref(&rdev->gart.table.vram.robj);
}
/*
* Common gart functions.
*/
void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
int pages)
{
unsigned t;
unsigned p;
int i, j;
if (!rdev->gart.ready) {
// WARN(1, "trying to unbind memory to unitialized GART !\n");
return;
}
t = offset / 4096;
p = t / (PAGE_SIZE / 4096);
for (i = 0; i < pages; i++, p++) {
if (rdev->gart.pages[p]) {
// pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p],
// PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
rdev->gart.pages[p] = NULL;
rdev->gart.pages_addr[p] = 0;
for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) {
radeon_gart_set_page(rdev, t, 0);
}
}
}
mb();
radeon_gart_tlb_flush(rdev);
}
int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
int pages, u32_t *pagelist)
{
unsigned t;
unsigned p;
uint64_t page_base;
int i, j;
dbgprintf("%s ",__FUNCTION__);
dbgprintf("offset %x pages %x list %x\n",
offset, pages, pagelist);
if (!rdev->gart.ready) {
DRM_ERROR("trying to bind memory to unitialized GART !\n");
return -EINVAL;
}
t = offset / 4096;
p = t / (PAGE_SIZE / 4096);
for (i = 0; i < pages; i++, p++) {
/* we need to support large memory configurations */
/* assume that unbind have already been call on the range */
rdev->gart.pages_addr[p] = pagelist[i] & ~4095;
//if (pci_dma_mapping_error(rdev->pdev, rdev->gart.pages_addr[p])) {
// /* FIXME: failed to map page (return -ENOMEM?) */
// radeon_gart_unbind(rdev, offset, pages);
// return -ENOMEM;
//}
rdev->gart.pages[p] = pagelist[i];
page_base = (uint32_t)rdev->gart.pages_addr[p];
for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) {
radeon_gart_set_page(rdev, t, page_base);
page_base += 4096;
}
}
mb();
radeon_gart_tlb_flush(rdev);
dbgprintf("done %s\n",__FUNCTION__);
return 0;
}
int radeon_gart_init(struct radeon_device *rdev)
{
dbgprintf("%s\n",__FUNCTION__);
if (rdev->gart.pages) {
return 0;
}
/* We need PAGE_SIZE >= 4096 */
if (PAGE_SIZE < 4096) {
DRM_ERROR("Page size is smaller than GPU page size!\n");
return -EINVAL;
}
/* Compute table size */
rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE;
rdev->gart.num_gpu_pages = rdev->mc.gtt_size / 4096;
DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",
rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages);
/* Allocate pages table */
rdev->gart.pages = kzalloc(sizeof(void *) * rdev->gart.num_cpu_pages,
GFP_KERNEL);
if (rdev->gart.pages == NULL) {
// radeon_gart_fini(rdev);
return -ENOMEM;
}
rdev->gart.pages_addr = kzalloc(sizeof(u32_t) *
rdev->gart.num_cpu_pages, GFP_KERNEL);
if (rdev->gart.pages_addr == NULL) {
// radeon_gart_fini(rdev);
return -ENOMEM;
}
return 0;
}
void radeon_gart_fini(struct radeon_device *rdev)
{
if (rdev->gart.pages && rdev->gart.pages_addr && rdev->gart.ready) {
/* unbind pages */
radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages);
}
rdev->gart.ready = false;
kfree(rdev->gart.pages);
kfree(rdev->gart.pages_addr);
rdev->gart.pages = NULL;
rdev->gart.pages_addr = NULL;
}

File diff suppressed because it is too large Load Diff

View File

@ -32,14 +32,15 @@
#include "radeon.h"
#include "atom.h"
extern void * ring_buffer;
#if 0
int radeon_debugfs_ib_init(struct radeon_device *rdev);
/*
* IB.
*/
#if 0
int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib)
{
struct radeon_fence *fence;
@ -98,6 +99,7 @@ out:
return r;
}
void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib)
{
struct radeon_ib *tmp = *ib;
@ -170,6 +172,7 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
mutex_unlock(&rdev->ib_pool.mutex);
return 0;
}
#endif
int radeon_ib_pool_init(struct radeon_device *rdev)
{
@ -210,9 +213,9 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
rdev->ib_pool.ready = true;
DRM_INFO("radeon: ib pool ready.\n");
if (radeon_debugfs_ib_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for IB !\n");
}
// if (radeon_debugfs_ib_init(rdev)) {
// DRM_ERROR("Failed to register debugfs file for IB !\n");
// }
return r;
}
@ -221,16 +224,18 @@ void radeon_ib_pool_fini(struct radeon_device *rdev)
if (!rdev->ib_pool.ready) {
return;
}
mutex_lock(&rdev->ib_pool.mutex);
// mutex_lock(&rdev->ib_pool.mutex);
bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
if (rdev->ib_pool.robj) {
radeon_object_kunmap(rdev->ib_pool.robj);
radeon_object_unref(&rdev->ib_pool.robj);
// radeon_object_kunmap(rdev->ib_pool.robj);
// radeon_object_unref(&rdev->ib_pool.robj);
rdev->ib_pool.robj = NULL;
}
mutex_unlock(&rdev->ib_pool.mutex);
// mutex_unlock(&rdev->ib_pool.mutex);
}
#if 0
int radeon_ib_test(struct radeon_device *rdev)
{
struct radeon_ib *ib;
@ -402,7 +407,6 @@ int radeon_ring_test(struct radeon_device *rdev)
int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
int pages, u32_t *pagelist);
#define page_tabs 0xFDC00000
int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size)
@ -413,8 +417,7 @@ int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size)
rdev->cp.ring_size = ring_size;
#if 0
/* Allocate ring buffer */
/* Allocate ring buffer */
if (rdev->cp.ring_obj == NULL) {
r = radeon_object_create(rdev, NULL, rdev->cp.ring_size,
true,
@ -442,23 +445,19 @@ int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size)
return r;
}
}
#endif
dbgprintf("ring size %x\n", ring_size);
// rdev->cp.ring = CreateRingBuffer( ring_size, PG_SW );
dbgprintf("ring buffer %x\n", rdev->cp.ring );
rdev->cp.ring = ring_buffer; //CreateRingBuffer( ring_size, PG_SW );
// rdev->cp.gpu_addr = rdev->mc.gtt_location;
dbgprintf("ring buffer %x\n", rdev->cp.ring );
// u32_t *pagelist = &((u32_t*)page_tabs)[(u32_t)rdev->cp.ring >> 12];
rdev->cp.gpu_addr = rdev->mc.gtt_location;
// dbgprintf("pagelist %x\n", pagelist);
u32_t *pagelist = &((u32_t*)page_tabs)[(u32_t)rdev->cp.ring >> 12];
dbgprintf("pagelist %x\n", pagelist);
radeon_gart_bind(rdev, 0, ring_size / 4096, pagelist);
// radeon_gart_bind(rdev, 0, ring_size / 4096, pagelist);
rdev->cp.ptr_mask = (rdev->cp.ring_size / 4) - 1;
rdev->cp.ring_free_dw = rdev->cp.ring_size / 4;

View File

@ -140,7 +140,7 @@ void rv515_ring_start(struct radeon_device *rdev)
unsigned gb_tile_config;
int r;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
/* Sub pixel 1/12 so we can have 4K rendering according to doc */
gb_tile_config = R300_ENABLE_TILING | R300_TILE_SIZE_16;
switch (rdev->num_gb_pipes) {
@ -231,7 +231,7 @@ void rv515_ring_start(struct radeon_device *rdev)
radeon_ring_write(rdev, 0);
radeon_ring_unlock_commit(rdev);
dbgprintf("done %s\n\r",__FUNCTION__);
dbgprintf("done %s\n",__FUNCTION__);
}
@ -296,7 +296,7 @@ int rv515_ga_reset(struct radeon_device *rdev)
bool reinit_cp;
int i;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
reinit_cp = rdev->cp.ready;
rdev->cp.ready = false;
@ -350,7 +350,7 @@ int rv515_gpu_reset(struct radeon_device *rdev)
{
uint32_t status;
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
/* reset order likely matter */
status = RREG32(RADEON_RBBM_STATUS);
@ -569,7 +569,7 @@ static const unsigned r500_reg_safe_bm[159] = {
int rv515_init(struct radeon_device *rdev)
{
dbgprintf("%s\n\r",__FUNCTION__);
dbgprintf("%s\n",__FUNCTION__);
rdev->config.r300.reg_safe_bm = r500_reg_safe_bm;
rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r500_reg_safe_bm);