[LIBUSB][USBCCGP]
[reactos.git] / reactos / drivers / usb / usbehci / physmem.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbehci/physmem.c
5 * PURPOSE: Common Buffer routines.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 */
9
10 #include "physmem.h"
11 #include "debug.h"
12
13 #define SMALL_ALLOCATION_SIZE 32
14
15 VOID
16 DumpPages()
17 {
18 //PMEM_HEADER MemBlock = (PMEM_HEADER)EhciSharedMemory.VirtualAddr;
19 }
20
21 // Returns Virtual Address of Allocated Memory
22 ULONG
23 AllocateMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Size, ULONG *PhysicalAddress)
24 {
25 PMEM_HEADER MemoryPage = NULL;
26 ULONG PageCount = 0;
27 ULONG NumberOfPages = hcd->CommonBufferSize / PAGE_SIZE;
28 ULONG BlocksNeeded = 0;
29 ULONG i,j, freeCount;
30 ULONG RetAddr = 0;
31
32 MemoryPage = (PMEM_HEADER)hcd->CommonBufferVA[0];
33 Size = ((Size + SMALL_ALLOCATION_SIZE - 1) / SMALL_ALLOCATION_SIZE) * SMALL_ALLOCATION_SIZE;
34 BlocksNeeded = Size / SMALL_ALLOCATION_SIZE;
35
36 do
37 {
38 if (MemoryPage->IsFull)
39 {
40 PageCount++;
41
42 if (!(PMEM_HEADER)hcd->CommonBufferVA[PageCount])
43 {
44 hcd->CommonBufferVA[PageCount] =
45 hcd->pDmaAdapter->DmaOperations->AllocateCommonBuffer(hcd->pDmaAdapter,
46 PAGE_SIZE,
47 &hcd->CommonBufferPA[PageCount],
48 FALSE);
49 }
50 MemoryPage = (PMEM_HEADER)hcd->CommonBufferVA[PageCount];
51 continue;
52 }
53 freeCount = 0;
54 for (i = 0; i < sizeof(MemoryPage->Entry); i++)
55 {
56 if (!MemoryPage->Entry[i].InUse)
57 {
58 freeCount++;
59 }
60 else
61 {
62 freeCount = 0;
63 }
64
65 if ((i-freeCount+1 + BlocksNeeded) > sizeof(MemoryPage->Entry))
66 {
67 freeCount = 0;
68 break;
69 }
70
71 if (freeCount == BlocksNeeded)
72 {
73 for (j = 0; j < freeCount; j++)
74 {
75 MemoryPage->Entry[i-j].InUse = 1;
76 MemoryPage->Entry[i-j].Blocks = 0;
77 }
78
79 MemoryPage->Entry[i-freeCount + 1].Blocks = BlocksNeeded;
80
81 RetAddr = (ULONG)MemoryPage + (SMALL_ALLOCATION_SIZE * (i - freeCount + 1)) + sizeof(MEM_HEADER);
82
83 *(ULONG*)PhysicalAddress = (ULONG)hcd->CommonBufferPA[PageCount].LowPart + (RetAddr - (ULONG)hcd->CommonBufferVA[PageCount]);
84
85 return RetAddr;
86 }
87 }
88
89 PageCount++;
90 if (!(PMEM_HEADER)hcd->CommonBufferVA[PageCount])
91 {
92
93 hcd->CommonBufferVA[PageCount] =
94 hcd->pDmaAdapter->DmaOperations->AllocateCommonBuffer(hcd->pDmaAdapter,
95 PAGE_SIZE,
96 &hcd->CommonBufferPA[PageCount],
97 FALSE);
98 DPRINT1("Allocated CommonBuffer VA %x, PA %x\n", hcd->CommonBufferVA[PageCount], hcd->CommonBufferPA[PageCount]);
99 }
100 MemoryPage = (PMEM_HEADER)hcd->CommonBufferVA[PageCount];
101
102 } while (PageCount < NumberOfPages);
103
104 if (PageCount == NumberOfPages)
105 ASSERT(FALSE);
106
107 return 0;
108 }
109
110 VOID
111 ReleaseMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Address)
112 {
113 PMEM_HEADER MemoryPage;
114 ULONG Index, i, BlockSize;
115
116 MemoryPage = (PMEM_HEADER)(Address & ~(PAGE_SIZE - 1));
117
118 Index = (Address - ((ULONG)MemoryPage + sizeof(MEM_HEADER))) / SMALL_ALLOCATION_SIZE;
119 BlockSize = MemoryPage->Entry[Index].Blocks;
120
121 for (i = 0; i < BlockSize; i++)
122 {
123 MemoryPage->Entry[Index + i].InUse = 0;
124 MemoryPage->Entry[Index + i].Blocks = 0;
125 }
126
127 if (MemoryPage != (PMEM_HEADER)hcd->CommonBufferVA[0])
128 {
129 for (i=0; i < sizeof(MemoryPage->Entry) / 2; i++)
130 {
131 if ((MemoryPage->Entry[i].InUse) || (MemoryPage->Entry[sizeof(MemoryPage->Entry) - i].InUse))
132 return;
133 }
134 DPRINT1("Freeing CommonBuffer VA %x, PA %x\n", MemoryPage, MmGetPhysicalAddress(MemoryPage));
135 hcd->pDmaAdapter->DmaOperations->FreeCommonBuffer(hcd->pDmaAdapter,
136 PAGE_SIZE,
137 MmGetPhysicalAddress(MemoryPage),
138 MemoryPage,
139 FALSE);
140 }
141 }