1*e13b1fa5SApple OSS Distributions /*
2*e13b1fa5SApple OSS Distributions  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3*e13b1fa5SApple OSS Distributions  *
4*e13b1fa5SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*e13b1fa5SApple OSS Distributions  *
6*e13b1fa5SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*e13b1fa5SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*e13b1fa5SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*e13b1fa5SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*e13b1fa5SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*e13b1fa5SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*e13b1fa5SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*e13b1fa5SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*e13b1fa5SApple OSS Distributions  *
15*e13b1fa5SApple OSS Distributions  * Please obtain a copy of the License at
16*e13b1fa5SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*e13b1fa5SApple OSS Distributions  *
18*e13b1fa5SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*e13b1fa5SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*e13b1fa5SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*e13b1fa5SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*e13b1fa5SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*e13b1fa5SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*e13b1fa5SApple OSS Distributions  * limitations under the License.
25*e13b1fa5SApple OSS Distributions  *
26*e13b1fa5SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*e13b1fa5SApple OSS Distributions  */
28*e13b1fa5SApple OSS Distributions 
29*e13b1fa5SApple OSS Distributions #include <IOKit/IOSharedDataQueue.h>
30*e13b1fa5SApple OSS Distributions #include <IOKit/IODataQueueShared.h>
31*e13b1fa5SApple OSS Distributions #include <IOKit/IOLib.h>
32*e13b1fa5SApple OSS Distributions #include <IOKit/IOMemoryDescriptor.h>
33*e13b1fa5SApple OSS Distributions 
34*e13b1fa5SApple OSS Distributions #ifdef dequeue
35*e13b1fa5SApple OSS Distributions #undef dequeue
36*e13b1fa5SApple OSS Distributions #endif
37*e13b1fa5SApple OSS Distributions 
38*e13b1fa5SApple OSS Distributions #define super IODataQueue
39*e13b1fa5SApple OSS Distributions 
40*e13b1fa5SApple OSS Distributions OSDefineMetaClassAndStructors(IOSharedDataQueue, IODataQueue)
41*e13b1fa5SApple OSS Distributions 
42*e13b1fa5SApple OSS Distributions IOSharedDataQueue *IOSharedDataQueue::withCapacity(UInt32 size)
43*e13b1fa5SApple OSS Distributions {
44*e13b1fa5SApple OSS Distributions     IOSharedDataQueue *dataQueue = new IOSharedDataQueue;
45*e13b1fa5SApple OSS Distributions 
46*e13b1fa5SApple OSS Distributions     if (dataQueue) {
47*e13b1fa5SApple OSS Distributions         if  (!dataQueue->initWithCapacity(size)) {
48*e13b1fa5SApple OSS Distributions             dataQueue->release();
49*e13b1fa5SApple OSS Distributions             dataQueue = 0;
50*e13b1fa5SApple OSS Distributions         }
51*e13b1fa5SApple OSS Distributions     }
52*e13b1fa5SApple OSS Distributions 
53*e13b1fa5SApple OSS Distributions     return dataQueue;
54*e13b1fa5SApple OSS Distributions }
55*e13b1fa5SApple OSS Distributions 
56*e13b1fa5SApple OSS Distributions IOSharedDataQueue *IOSharedDataQueue::withEntries(UInt32 numEntries, UInt32 entrySize)
57*e13b1fa5SApple OSS Distributions {
58*e13b1fa5SApple OSS Distributions     IOSharedDataQueue *dataQueue = new IOSharedDataQueue;
59*e13b1fa5SApple OSS Distributions 
60*e13b1fa5SApple OSS Distributions     if (dataQueue) {
61*e13b1fa5SApple OSS Distributions         if (!dataQueue->initWithEntries(numEntries, entrySize)) {
62*e13b1fa5SApple OSS Distributions             dataQueue->release();
63*e13b1fa5SApple OSS Distributions             dataQueue = 0;
64*e13b1fa5SApple OSS Distributions         }
65*e13b1fa5SApple OSS Distributions     }
66*e13b1fa5SApple OSS Distributions 
67*e13b1fa5SApple OSS Distributions     return dataQueue;
68*e13b1fa5SApple OSS Distributions }
69*e13b1fa5SApple OSS Distributions 
70*e13b1fa5SApple OSS Distributions Boolean IOSharedDataQueue::initWithCapacity(UInt32 size)
71*e13b1fa5SApple OSS Distributions {
72*e13b1fa5SApple OSS Distributions     IODataQueueAppendix *   appendix;
73*e13b1fa5SApple OSS Distributions 
74*e13b1fa5SApple OSS Distributions     if (!super::init()) {
75*e13b1fa5SApple OSS Distributions         return false;
76*e13b1fa5SApple OSS Distributions     }
77*e13b1fa5SApple OSS Distributions 
78*e13b1fa5SApple OSS Distributions     dataQueue = (IODataQueueMemory *)IOMallocAligned(round_page_32(size + DATA_QUEUE_MEMORY_HEADER_SIZE + DATA_QUEUE_MEMORY_APPENDIX_SIZE), PAGE_SIZE);
79*e13b1fa5SApple OSS Distributions     if (dataQueue == 0) {
80*e13b1fa5SApple OSS Distributions         return false;
81*e13b1fa5SApple OSS Distributions     }
82*e13b1fa5SApple OSS Distributions 
83*e13b1fa5SApple OSS Distributions     dataQueue->queueSize    = size;
84*e13b1fa5SApple OSS Distributions     dataQueue->head         = 0;
85*e13b1fa5SApple OSS Distributions     dataQueue->tail         = 0;
86*e13b1fa5SApple OSS Distributions 
87*e13b1fa5SApple OSS Distributions     appendix            = (IODataQueueAppendix *)((UInt8 *)dataQueue + size + DATA_QUEUE_MEMORY_HEADER_SIZE);
88*e13b1fa5SApple OSS Distributions     appendix->version   = 0;
89*e13b1fa5SApple OSS Distributions     notifyMsg           = &(appendix->msgh);
90*e13b1fa5SApple OSS Distributions     setNotificationPort(MACH_PORT_NULL);
91*e13b1fa5SApple OSS Distributions 
92*e13b1fa5SApple OSS Distributions     return true;
93*e13b1fa5SApple OSS Distributions }
94*e13b1fa5SApple OSS Distributions 
95*e13b1fa5SApple OSS Distributions void IOSharedDataQueue::free()
96*e13b1fa5SApple OSS Distributions {
97*e13b1fa5SApple OSS Distributions     if (dataQueue) {
98*e13b1fa5SApple OSS Distributions         IOFreeAligned(dataQueue, round_page_32(dataQueue->queueSize + DATA_QUEUE_MEMORY_HEADER_SIZE + DATA_QUEUE_MEMORY_APPENDIX_SIZE));
99*e13b1fa5SApple OSS Distributions         dataQueue = NULL;
100*e13b1fa5SApple OSS Distributions     }
101*e13b1fa5SApple OSS Distributions 
102*e13b1fa5SApple OSS Distributions     super::free();
103*e13b1fa5SApple OSS Distributions }
104*e13b1fa5SApple OSS Distributions 
105*e13b1fa5SApple OSS Distributions IOMemoryDescriptor *IOSharedDataQueue::getMemoryDescriptor()
106*e13b1fa5SApple OSS Distributions {
107*e13b1fa5SApple OSS Distributions     IOMemoryDescriptor *descriptor = 0;
108*e13b1fa5SApple OSS Distributions 
109*e13b1fa5SApple OSS Distributions     if (dataQueue != 0) {
110*e13b1fa5SApple OSS Distributions         descriptor = IOMemoryDescriptor::withAddress(dataQueue, dataQueue->queueSize + DATA_QUEUE_MEMORY_HEADER_SIZE + DATA_QUEUE_MEMORY_APPENDIX_SIZE, kIODirectionOutIn);
111*e13b1fa5SApple OSS Distributions     }
112*e13b1fa5SApple OSS Distributions 
113*e13b1fa5SApple OSS Distributions     return descriptor;
114*e13b1fa5SApple OSS Distributions }
115*e13b1fa5SApple OSS Distributions 
116*e13b1fa5SApple OSS Distributions 
117*e13b1fa5SApple OSS Distributions IODataQueueEntry * IOSharedDataQueue::peek()
118*e13b1fa5SApple OSS Distributions {
119*e13b1fa5SApple OSS Distributions     IODataQueueEntry *entry = 0;
120*e13b1fa5SApple OSS Distributions 
121*e13b1fa5SApple OSS Distributions     if (dataQueue && (dataQueue->head != dataQueue->tail)) {
122*e13b1fa5SApple OSS Distributions         IODataQueueEntry *  head		= 0;
123*e13b1fa5SApple OSS Distributions         UInt32              headSize    = 0;
124*e13b1fa5SApple OSS Distributions         UInt32              headOffset  = dataQueue->head;
125*e13b1fa5SApple OSS Distributions         UInt32              queueSize   = dataQueue->queueSize;
126*e13b1fa5SApple OSS Distributions 
127*e13b1fa5SApple OSS Distributions         head 		= (IODataQueueEntry *)((char *)dataQueue->queue + headOffset);
128*e13b1fa5SApple OSS Distributions         headSize 	= head->size;
129*e13b1fa5SApple OSS Distributions 
130*e13b1fa5SApple OSS Distributions 		// Check if there's enough room before the end of the queue for a header.
131*e13b1fa5SApple OSS Distributions         // If there is room, check if there's enough room to hold the header and
132*e13b1fa5SApple OSS Distributions         // the data.
133*e13b1fa5SApple OSS Distributions 
134*e13b1fa5SApple OSS Distributions         if ((headOffset + DATA_QUEUE_ENTRY_HEADER_SIZE > queueSize) ||
135*e13b1fa5SApple OSS Distributions             ((headOffset + headSize + DATA_QUEUE_ENTRY_HEADER_SIZE) > queueSize))
136*e13b1fa5SApple OSS Distributions         {
137*e13b1fa5SApple OSS Distributions             // No room for the header or the data, wrap to the beginning of the queue.
138*e13b1fa5SApple OSS Distributions             entry = dataQueue->queue;
139*e13b1fa5SApple OSS Distributions         } else {
140*e13b1fa5SApple OSS Distributions             entry = head;
141*e13b1fa5SApple OSS Distributions         }
142*e13b1fa5SApple OSS Distributions     }
143*e13b1fa5SApple OSS Distributions 
144*e13b1fa5SApple OSS Distributions     return entry;
145*e13b1fa5SApple OSS Distributions }
146*e13b1fa5SApple OSS Distributions 
147*e13b1fa5SApple OSS Distributions Boolean IOSharedDataQueue::dequeue(void *data, UInt32 *dataSize)
148*e13b1fa5SApple OSS Distributions {
149*e13b1fa5SApple OSS Distributions     Boolean             retVal          = TRUE;
150*e13b1fa5SApple OSS Distributions     IODataQueueEntry *  entry           = 0;
151*e13b1fa5SApple OSS Distributions     UInt32              entrySize       = 0;
152*e13b1fa5SApple OSS Distributions     UInt32              newHeadOffset   = 0;
153*e13b1fa5SApple OSS Distributions 
154*e13b1fa5SApple OSS Distributions     if (dataQueue) {
155*e13b1fa5SApple OSS Distributions         if (dataQueue->head != dataQueue->tail) {
156*e13b1fa5SApple OSS Distributions             IODataQueueEntry *  head		= 0;
157*e13b1fa5SApple OSS Distributions             UInt32              headSize    = 0;
158*e13b1fa5SApple OSS Distributions             UInt32              headOffset  = dataQueue->head;
159*e13b1fa5SApple OSS Distributions             UInt32              queueSize   = dataQueue->queueSize;
160*e13b1fa5SApple OSS Distributions 
161*e13b1fa5SApple OSS Distributions             head 		= (IODataQueueEntry *)((char *)dataQueue->queue + headOffset);
162*e13b1fa5SApple OSS Distributions             headSize 	= head->size;
163*e13b1fa5SApple OSS Distributions 
164*e13b1fa5SApple OSS Distributions             // we wraped around to beginning, so read from there
165*e13b1fa5SApple OSS Distributions 			// either there was not even room for the header
166*e13b1fa5SApple OSS Distributions 			if ((headOffset + DATA_QUEUE_ENTRY_HEADER_SIZE > queueSize) ||
167*e13b1fa5SApple OSS Distributions 				// or there was room for the header, but not for the data
168*e13b1fa5SApple OSS Distributions 				((headOffset + headSize + DATA_QUEUE_ENTRY_HEADER_SIZE) > queueSize)) {
169*e13b1fa5SApple OSS Distributions                 entry           = dataQueue->queue;
170*e13b1fa5SApple OSS Distributions                 entrySize       = entry->size;
171*e13b1fa5SApple OSS Distributions                 newHeadOffset   = entrySize + DATA_QUEUE_ENTRY_HEADER_SIZE;
172*e13b1fa5SApple OSS Distributions             // else it is at the end
173*e13b1fa5SApple OSS Distributions             } else {
174*e13b1fa5SApple OSS Distributions                 entry           = head;
175*e13b1fa5SApple OSS Distributions                 entrySize       = entry->size;
176*e13b1fa5SApple OSS Distributions                 newHeadOffset   = headOffset + entrySize + DATA_QUEUE_ENTRY_HEADER_SIZE;
177*e13b1fa5SApple OSS Distributions             }
178*e13b1fa5SApple OSS Distributions         }
179*e13b1fa5SApple OSS Distributions 
180*e13b1fa5SApple OSS Distributions         if (entry) {
181*e13b1fa5SApple OSS Distributions             if (data) {
182*e13b1fa5SApple OSS Distributions                 if (dataSize) {
183*e13b1fa5SApple OSS Distributions                     if (entrySize <= *dataSize) {
184*e13b1fa5SApple OSS Distributions                         memcpy(data, &(entry->data), entrySize);
185*e13b1fa5SApple OSS Distributions                         dataQueue->head = newHeadOffset;
186*e13b1fa5SApple OSS Distributions                     } else {
187*e13b1fa5SApple OSS Distributions                         retVal = FALSE;
188*e13b1fa5SApple OSS Distributions                     }
189*e13b1fa5SApple OSS Distributions                 } else {
190*e13b1fa5SApple OSS Distributions                     retVal = FALSE;
191*e13b1fa5SApple OSS Distributions                 }
192*e13b1fa5SApple OSS Distributions             } else {
193*e13b1fa5SApple OSS Distributions                 dataQueue->head = newHeadOffset;
194*e13b1fa5SApple OSS Distributions             }
195*e13b1fa5SApple OSS Distributions 
196*e13b1fa5SApple OSS Distributions             if (dataSize) {
197*e13b1fa5SApple OSS Distributions                 *dataSize = entrySize;
198*e13b1fa5SApple OSS Distributions             }
199*e13b1fa5SApple OSS Distributions         } else {
200*e13b1fa5SApple OSS Distributions             retVal = FALSE;
201*e13b1fa5SApple OSS Distributions         }
202*e13b1fa5SApple OSS Distributions     } else {
203*e13b1fa5SApple OSS Distributions         retVal = FALSE;
204*e13b1fa5SApple OSS Distributions     }
205*e13b1fa5SApple OSS Distributions 
206*e13b1fa5SApple OSS Distributions     return retVal;
207*e13b1fa5SApple OSS Distributions }
208*e13b1fa5SApple OSS Distributions 
209*e13b1fa5SApple OSS Distributions 
210*e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 0);
211*e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 1);
212*e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 2);
213*e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 3);
214*e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 4);
215*e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 5);
216*e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 6);
217*e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 7);
218