1/* 2 * SiS 190/191 NIC Driver. 3 * Copyright (c) 2009 S.Zharski <imker@gmx.li> 4 * Distributed under the terms of the MIT license. 5 * 6 */ 7#ifndef _SiS19X_DATARING_H_ 8#define _SiS19X_DATARING_H_ 9 10 11#include <KernelExport.h> 12 13#include "Driver.h" 14#include "Registers.h" 15#include "Settings.h" 16 17 18class Device; 19 20template<typename __type, uint32 __count> 21class DataRing { 22public: 23 DataRing(Device* device, bool isTx); 24 ~DataRing(); 25 26 status_t Open(); 27 void CleanUp(); 28 status_t Close(); 29 30 status_t Read(uint8* buffer, size_t* numBytes); 31 status_t Write(const uint8* buffer, size_t* numBytes); 32 33 int32 InterruptHandler(); 34 35 void Trace(); 36 void Dump(); 37 38private: 39 status_t _InitArea(); 40 void _SetBaseAddress(phys_addr_t address); 41 42 Device* fDevice; 43 bool fIsTx; 44 status_t fStatus; 45 area_id fArea; 46 int32 fSpinlock; 47 sem_id fSemaphore; 48 uint32 fHead; 49 uint32 fTail; 50 51 volatile __type* fDescriptors; 52 volatile uint8* fBuffers[__count]; 53}; 54 55 56 57template<typename __type, uint32 __count> 58DataRing<__type, __count>::DataRing(Device* device, bool isTx) 59 : 60 fDevice(device), 61 fIsTx(isTx), 62 fStatus(B_NO_INIT), 63 fArea(-1), 64 fSpinlock(0), 65 fSemaphore(0), 66 fHead(0), 67 fTail(0), 68 fDescriptors(NULL) 69{ 70 memset(fBuffers, 0, sizeof(fBuffers)); 71} 72 73 74template<typename __type, uint32 __count> 75DataRing<__type, __count>::~DataRing() 76{ 77 delete_sem(fSemaphore); 78 delete_area(fArea); 79} 80 81 82template<typename __type, uint32 __count> 83status_t 84DataRing<__type, __count>::_InitArea() 85{ 86 // create area for xfer data descriptors and buffers... 87 // 88 // layout is following: 89 // | descriptors array | buffers array | 90 // 91 uint32 buffSize = BufferSize + sizeof(__type); 92 buffSize *= __count; 93 buffSize = (buffSize + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); 94 fArea = create_area(DRIVER_NAME "_data_ring", (void**)&fDescriptors, 95 B_ANY_KERNEL_ADDRESS, buffSize, 96 B_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA); 97 if (fArea < 0) { 98 TRACE_ALWAYS("Cannot create area with size %d bytes:%#010x\n", 99 buffSize, fArea); 100 return fStatus = fArea; 101 } 102 103 // setup descriptors and buffers layout 104 uint8* buffersData = (uint8*)fDescriptors; 105 uint32 descriptorsSize = sizeof(__type) * __count; 106 buffersData += descriptorsSize; 107 108 physical_entry table = {0}; 109 110 for (size_t i = 0; i < __count; i++) { 111 fBuffers[i] = buffersData + BufferSize * i; 112 113 get_memory_map((void*)fBuffers[i], BufferSize, &table, 1); 114 fDescriptors[i].Init(table.address, i == (__count - 1)); 115 } 116 117 get_memory_map((void*)fDescriptors, descriptorsSize, &table, 1); 118 119 _SetBaseAddress(table.address); 120 121 return fStatus = B_OK; 122} 123 124 125template<typename __type, uint32 __count> 126status_t 127DataRing<__type, __count>::Open() 128{ 129 if (fStatus != B_OK && _InitArea() != B_OK) { 130 return fStatus; 131 } 132 133 if (fIsTx) { 134 fSemaphore = create_sem(__count, "SiS19X Transmit"); 135 } else { 136 fSemaphore = create_sem(0, "SiS19X Receive"); 137 } 138 139 if (fSemaphore < 0) { 140 TRACE_ALWAYS("Cannot create %s semaphore:%#010x\n", 141 fIsTx ? "transmit" : "receive", fSemaphore); 142 return fStatus = fSemaphore; 143 } 144 145 set_sem_owner(fSemaphore, B_SYSTEM_TEAM); 146 147 return fStatus = B_OK; 148} 149 150 151template<typename __type, uint32 __count> 152status_t 153DataRing<__type, __count>::Close() 154{ 155 delete_sem(fSemaphore); 156 fSemaphore = 0; 157 158 return B_OK; 159} 160 161 162template<typename __type, uint32 __count> 163void 164DataRing<__type, __count>::Trace() 165{ 166 int32 count = 0; 167 get_sem_count(fSemaphore, &count); 168 TRACE_ALWAYS("%s:[count:%d] n:%lu l:%lu d:%lu\n", fIsTx ? "Tx" : "Rx", 169 count, fHead, fTail, fHead - fTail); 170} 171 172 173#endif //_SiS19X_DATARING_H_ 174 175