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:
Michael Phipps 2002-12-21 07:47:05 +00:00
parent 744a457218
commit bf738c95da
10 changed files with 155 additions and 11 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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.

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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");

View File

@ -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;}