Added the device driver API that Axel reminded me about.
Updated the TODO list. This is 99% feature complete. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2271 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
744a457218
commit
bf738c95da
@ -1,5 +1,6 @@
|
||||
1) Change the architecture so that instead of multiple threads of tests, we have multiple apps of tests...
|
||||
2) Tests are not done.
|
||||
1) Implement the sharing methodology of mmap (PRIVATE vs SHARED, etc)
|
||||
2) Change the architecture so that instead of multiple threads of tests, we have multiple apps of tests...
|
||||
3) Tests are not done.
|
||||
Test:
|
||||
getNextAreaInfo
|
||||
cloneArea
|
||||
|
@ -165,7 +165,7 @@ status_t area::getInfo(area_info *dest) {
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
bool area::contains(void *address) {
|
||||
bool area::contains(const void *address) {
|
||||
unsigned long base=(unsigned long)(address);
|
||||
// error ("area::contains: looking for %d in %d -- %d, value = %d\n",base,start_address,end_address, ((start_address<=base) && (end_address>=base)));
|
||||
|
||||
@ -292,3 +292,46 @@ void area::dump(void) {
|
||||
}
|
||||
}
|
||||
|
||||
long area::get_memory_map(const void *address, ulong numBytes, physical_entry *table, long numEntries) {
|
||||
unsigned long vbase=(unsigned long)address;
|
||||
long prevMem=0,tableEntry=-1;
|
||||
// Cycle over each "page to find";
|
||||
for (int byteOffset=0;byteOffset<=numBytes;byteOffset+=PAGE_SIZE) {
|
||||
vpage search(vbase+byteOffset);
|
||||
vpage *found=reinterpret_cast<vpage *>(vpages.find(&search));
|
||||
if (!found) return B_ERROR;
|
||||
unsigned long mem=found->getPhysPage()->getAddress();
|
||||
if (mem!=prevMem+PAGE_SIZE) {
|
||||
if (++tableEntry==numEntries)
|
||||
return B_ERROR; // Ran out of places to fill in
|
||||
prevMem=mem;
|
||||
table[tableEntry].address=(void *)mem;
|
||||
}
|
||||
table[tableEntry].size+=PAGE_SIZE;
|
||||
}
|
||||
if (++tableEntry==numEntries)
|
||||
return B_ERROR; // Ran out of places to fill in
|
||||
table[tableEntry].size=0;
|
||||
}
|
||||
|
||||
long area::lock_memory(void *address, ulong numBytes, ulong flags) {
|
||||
unsigned long vbase=(unsigned long)address;
|
||||
for (int byteOffset=0;byteOffset<=numBytes;byteOffset+=PAGE_SIZE) {
|
||||
vpage search(vbase+byteOffset);
|
||||
vpage *found=reinterpret_cast<vpage *>(vpages.find(&search));
|
||||
if (!found) return B_ERROR;
|
||||
if (!found->lock(flags)) return B_ERROR;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
long area::unlock_memory(void *address, ulong numBytes, ulong flags) {
|
||||
unsigned long vbase=(unsigned long)address;
|
||||
for (int byteOffset=0;byteOffset<=numBytes;byteOffset+=PAGE_SIZE) {
|
||||
vpage search(vbase+byteOffset);
|
||||
vpage *found=reinterpret_cast<vpage *>(vpages.find(&search));
|
||||
if (!found) return B_ERROR;
|
||||
found->unlock(flags);
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -39,6 +39,9 @@ class area : public node
|
||||
void setAreaID(int id) {areaID=id;}
|
||||
status_t setProtection(protectType prot);
|
||||
status_t resize(size_t newSize);
|
||||
long get_memory_map(const void *address, ulong numBytes, physical_entry *table, long numEntries);
|
||||
long lock_memory(void *address, ulong numBytes, ulong flags);
|
||||
long unlock_memory(void *address, ulong numBytes, ulong flags);
|
||||
|
||||
// Accessors
|
||||
status_t getInfo(area_info *dest);
|
||||
@ -59,7 +62,7 @@ class area : public node
|
||||
// Comparisson with others
|
||||
bool nameMatch(char *matchName) {return (strcmp(matchName,name)==0);}
|
||||
bool couldAdd(unsigned long start,unsigned long end) { return ((end<start_address) || (start>end_address));}
|
||||
bool contains(void *address);
|
||||
bool contains(const void *address);
|
||||
|
||||
// External methods for "server" type calls
|
||||
void pager(int desperation);
|
||||
|
@ -83,7 +83,7 @@ area *areaManager::findArea(char *address) {
|
||||
}
|
||||
|
||||
// Loops over our areas looking for the one whose virtual address matches the passed in address
|
||||
area *areaManager::findArea(void *address) {
|
||||
area *areaManager::findArea(const void *address) {
|
||||
// THIS DOES NOT HAVE LOCKING - all callers must lock.
|
||||
// error ("Finding area by void * address\n");
|
||||
for (struct node *cur=areas.rock;cur;cur=cur->next)
|
||||
@ -327,3 +327,38 @@ status_t areaManager::munmap(void *addr,size_t len)
|
||||
unlock();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
long areaManager::get_memory_map(const void *address, ulong numBytes, physical_entry *table, long numEntries) {
|
||||
long retVal = B_ERROR; // Be pessimistic
|
||||
lock();
|
||||
// First, figure out what area we should be talking about...
|
||||
area *myArea=findArea(address);
|
||||
if (myArea)
|
||||
retVal = myArea->get_memory_map(address, numBytes,table,numEntries);
|
||||
unlock();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
long areaManager::lock_memory(void *address, ulong numBytes, ulong flags) {
|
||||
long retVal = B_ERROR; // Be pessimistic
|
||||
lock();
|
||||
// First, figure out what area we should be talking about...
|
||||
area *myArea=findArea(address);
|
||||
if (myArea)
|
||||
retVal = myArea->lock_memory(address, numBytes,flags);
|
||||
unlock();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
long areaManager::unlock_memory(void *address, ulong numBytes, ulong flags) {
|
||||
long retVal = B_ERROR; // Be pessimistic
|
||||
lock();
|
||||
// First, figure out what area we should be talking about...
|
||||
area *myArea=findArea(address);
|
||||
if (myArea)
|
||||
retVal = myArea->unlock_memory(address, numBytes,flags);
|
||||
unlock();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ class areaManager // One of these per process
|
||||
status_t munmap(void *addr,size_t len);
|
||||
|
||||
// Mutators
|
||||
area *findArea(void *address);
|
||||
area *findArea(const void *address);
|
||||
area *findAreaLock(void *address);
|
||||
area *findArea(char *address);
|
||||
area *findArea(area_id id);
|
||||
@ -90,6 +90,9 @@ class areaManager // One of these per process
|
||||
}
|
||||
void lock() { acquire_sem(myLock); }
|
||||
void unlock() {release_sem(myLock);}
|
||||
long get_memory_map(const void *address, ulong numBytes, physical_entry *table, long numEntries);
|
||||
long lock_memory(void *address, ulong numBytes, ulong flags);
|
||||
long unlock_memory(void *address, ulong numBytes, ulong flags);
|
||||
|
||||
// External methods for "server" type calls
|
||||
bool fault(void *fault_address, bool writeError); // true = OK, false = panic.
|
||||
|
@ -44,4 +44,11 @@ enum pageState {FULL,CONTIGUOUS,LAZY,NO_LOCK,LOMEM};
|
||||
#define CACHE_BEGIN 0x90000000
|
||||
#define CACHE_END 0xe0000000
|
||||
|
||||
#define B_DMA_IO 0x00000001
|
||||
#define B_READ_DEVICE 0x00000002
|
||||
|
||||
struct physical_entry {void *address;
|
||||
ulong size;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -226,3 +226,26 @@ status_t vmInterface::munmap(void *addr, size_t len)
|
||||
retVal = getAM()->munmap(addr,len);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Driver Interface
|
||||
long vmInterface::get_memory_map(const void *address, ulong numBytes, physical_entry *table, long numEntries) {
|
||||
getAM()->get_memory_map(address, numBytes,table,numEntries);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
long vmInterface::lock_memory(void *address, ulong numBytes, ulong flags) {
|
||||
return getAM()->lock_memory(address,numBytes,flags);
|
||||
}
|
||||
|
||||
long vmInterface::unlock_memory(void *address, ulong numBytes, ulong flags) {
|
||||
return getAM()->unlock_memory(address,numBytes,flags);
|
||||
}
|
||||
|
||||
area_id vmInterface::map_physical_memory(const char *areaName, void *physAddress, size_t bytes, uint32 spec, uint32 protectionIn, void **vaddress) {
|
||||
int pages=(bytes + (PAGE_SIZE) - 1)/PAGE_SIZE;
|
||||
addressSpec as=(addressSpec) spec;
|
||||
protectType pro=(protectType) protectionIn;
|
||||
return getAM()->createArea((char *)areaName, pages, vaddress, as, LAZY, pro);
|
||||
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,14 @@ class vmInterface // This is the class that "owns" all of the managers.
|
||||
void cleaner(void);
|
||||
status_t writeCachedBlock(int fd, size_t offset, void *data);
|
||||
status_t readCachedBlock(int fd, size_t offset, void *data);
|
||||
|
||||
// Driver Interface
|
||||
long get_memory_map(const void *address, ulong numBytes, physical_entry *table, long numEntries);
|
||||
long lock_memory(void *address, ulong numBytes, ulong flags);
|
||||
long unlock_memory(void *address, ulong numBytes, ulong flags);
|
||||
area_id map_physical_memory(const char *areaName, void *physAddress, size_t bytes, uint32 spec, uint32 protection, void **vaddress);
|
||||
|
||||
|
||||
char getByte(unsigned long offset) {return getAM()->getByte(offset);} // This is for testing only
|
||||
void setByte(unsigned long offset,char value) {getAM()->setByte(offset,value);} // This is for testing only
|
||||
int getInt(unsigned long offset) {return getAM()->getInt(offset);} // This is for testing only
|
||||
|
@ -34,7 +34,7 @@ void vpage::refresh(void) {
|
||||
}
|
||||
|
||||
// Simple, empty constructor
|
||||
vpage::vpage(void) : physPage(NULL),backingNode(NULL),protection(none),dirty(false),swappable(false),start_address(0),end_address(0)
|
||||
vpage::vpage(void) : physPage(NULL),backingNode(NULL),protection(none),dirty(false),swappable(false),start_address(0),end_address(0), locked(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -137,6 +137,23 @@ bool vpage::fault(void *fault_address, bool writeError, int &in_count) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vpage::lock(long flags) {
|
||||
locked=true;
|
||||
if (!physPage) {
|
||||
physPage=vmBlock->pageMan->getPage();
|
||||
if (!physPage)
|
||||
return false;
|
||||
refresh();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void vpage::unlock(long flags) {
|
||||
if ((flags & B_DMA_IO) || (!(flags & B_READ_DEVICE)))
|
||||
dirty=true;
|
||||
locked=false;
|
||||
}
|
||||
|
||||
char vpage::getByte(unsigned long address,areaManager *manager) {
|
||||
// error ("vpage::getByte: address = %ld\n",address );
|
||||
if (!physPage)
|
||||
@ -180,10 +197,10 @@ bool vpage::pager(int desperation) {
|
||||
error ("vpage::pager swappable\n");
|
||||
switch (desperation) {
|
||||
case 1: return false; break;
|
||||
case 2: if (!physPage || protection!=readable) return false;break;
|
||||
case 3: if (!physPage || dirty) return false;break;
|
||||
case 4: if (!physPage) return false;break;
|
||||
case 5: if (!physPage) return false;break;
|
||||
case 2: if (!physPage || protection!=readable || locked) return false;break;
|
||||
case 3: if (!physPage || dirty || locked) return false;break;
|
||||
case 4: if (!physPage || locked) return false;break;
|
||||
case 5: if (!physPage || locked) return false;break;
|
||||
default: return false;break;
|
||||
}
|
||||
error ("vpage::pager flushing\n");
|
||||
|
@ -13,6 +13,7 @@ class vpage : public node
|
||||
protectType protection;
|
||||
bool dirty;
|
||||
bool swappable;
|
||||
bool locked;
|
||||
unsigned long start_address;
|
||||
unsigned long end_address;
|
||||
public:
|
||||
@ -27,6 +28,9 @@ class vpage : public node
|
||||
void setProtection(protectType prot);
|
||||
void flush(void); // write page to vnode, if necessary
|
||||
void refresh(void); // Read page back in from vnode
|
||||
bool lock(long flags); // lock this page into memory
|
||||
void unlock(long flags); // unlock this page from memory
|
||||
|
||||
|
||||
// Accessors
|
||||
protectType getProtection(void) {return protection;}
|
||||
|
Loading…
Reference in New Issue
Block a user