/*
* SiS 190/191 NIC Driver.
* Copyright (c) 2009 S.Zharski <imker@gmx.li>
* Distributed under the terms of the MIT license.
*
*/
#ifndef _SiS19X_DATARING_H_
#define _SiS19X_DATARING_H_
#include <KernelExport.h>
#include "Driver.h"
#include "Registers.h"
#include "Settings.h"
class Device;
template<typename __type, uint32 __count>
class DataRing {
public:
DataRing(Device* device, bool isTx);
~DataRing();
status_t Open();
void CleanUp();
status_t Close();
status_t Read(uint8* buffer, size_t* numBytes);
status_t Write(const uint8* buffer, size_t* numBytes);
int32 InterruptHandler();
void Trace();
void Dump();
private:
status_t _InitArea();
void _SetBaseAddress(phys_addr_t address);
Device* fDevice;
bool fIsTx;
status_t fStatus;
area_id fArea;
spinlock fSpinlock;
sem_id fSemaphore;
uint32 fHead;
uint32 fTail;
volatile __type* fDescriptors;
volatile uint8* fBuffers[__count];
};
template<typename __type, uint32 __count>
DataRing<__type, __count>::DataRing(Device* device, bool isTx)
:
fDevice(device),
fIsTx(isTx),
fStatus(B_NO_INIT),
fArea(-1),
fSemaphore(0),
fHead(0),
fTail(0),
fDescriptors(NULL)
{
B_INITIALIZE_SPINLOCK(&fSpinlock);
memset(fBuffers, 0, sizeof(fBuffers));
}
template<typename __type, uint32 __count>
DataRing<__type, __count>::~DataRing()
{
delete_sem(fSemaphore);
delete_area(fArea);
}
template<typename __type, uint32 __count>
status_t
DataRing<__type, __count>::_InitArea()
{
// create area for xfer data descriptors and buffers...
//
// layout is following:
// | descriptors array | buffers array |
//
uint32 buffSize = BufferSize + sizeof(__type);
buffSize *= __count;
buffSize = (buffSize + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
fArea = create_area(DRIVER_NAME "_data_ring", (void**)&fDescriptors,
B_ANY_KERNEL_ADDRESS, buffSize,
B_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA);
if (fArea < 0) {
TRACE_ALWAYS("Cannot create area with size %d bytes:%#010x\n",
buffSize, fArea);
return fStatus = fArea;
}
// setup descriptors and buffers layout
uint8* buffersData = (uint8*)fDescriptors;
uint32 descriptorsSize = sizeof(__type) * __count;
buffersData += descriptorsSize;
physical_entry table = {0};
for (size_t i = 0; i < __count; i++) {
fBuffers[i] = buffersData + BufferSize * i;
get_memory_map((void*)fBuffers[i], BufferSize, &table, 1);
fDescriptors[i].Init(table.address, i == (__count - 1));
}
get_memory_map((void*)fDescriptors, descriptorsSize, &table, 1);
_SetBaseAddress(table.address);
return fStatus = B_OK;
}
template<typename __type, uint32 __count>
status_t
DataRing<__type, __count>::Open()
{
if (fStatus != B_OK && _InitArea() != B_OK) {
return fStatus;
}
if (fIsTx) {
fSemaphore = create_sem(__count, "SiS19X Transmit");
} else {
fSemaphore = create_sem(0, "SiS19X Receive");
}
if (fSemaphore < 0) {
TRACE_ALWAYS("Cannot create %s semaphore:%#010x\n",
fIsTx ? "transmit" : "receive", fSemaphore);
return fStatus = fSemaphore;
}
set_sem_owner(fSemaphore, B_SYSTEM_TEAM);
return fStatus = B_OK;
}
template<typename __type, uint32 __count>
status_t
DataRing<__type, __count>::Close()
{
delete_sem(fSemaphore);
fSemaphore = 0;
return B_OK;
}
template<typename __type, uint32 __count>
void
DataRing<__type, __count>::Trace()
{
int32 count = 0;
get_sem_count(fSemaphore, &count);
TRACE_ALWAYS("%s:[count:%d] n:%lu l:%lu d:%lu\n", fIsTx ? "Tx" : "Rx",
count, fHead, fTail, fHead - fTail);
}
#endif //_SiS19X_DATARING_H_
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: fSpinlock.