1/*
2 * Copyright (c) 1998-2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License").  You may not use this file except in compliance with the
9 * License.  Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * IOPacketQueue.cpp - Implements a FIFO mbuf packet queue.
24 *
25 * HISTORY
26 * 9-Dec-1998       Joe Liu (jliu) created.
27 *
28 */
29
30#include <IOKit/assert.h>
31#include <IOKit/IOLib.h>    // IOLog
32#include <IOKit/network/IOPacketQueue.h>
33#include "IOMbufQueue.h"
34
35#define super OSObject
36OSDefineMetaClassAndStructors( IOPacketQueue, OSObject )
37OSMetaClassDefineReservedUnused( IOPacketQueue,  0);
38OSMetaClassDefineReservedUnused( IOPacketQueue,  1);
39OSMetaClassDefineReservedUnused( IOPacketQueue,  2);
40OSMetaClassDefineReservedUnused( IOPacketQueue,  3);
41OSMetaClassDefineReservedUnused( IOPacketQueue,  4);
42OSMetaClassDefineReservedUnused( IOPacketQueue,  5);
43OSMetaClassDefineReservedUnused( IOPacketQueue,  6);
44OSMetaClassDefineReservedUnused( IOPacketQueue,  7);
45OSMetaClassDefineReservedUnused( IOPacketQueue,  8);
46OSMetaClassDefineReservedUnused( IOPacketQueue,  9);
47OSMetaClassDefineReservedUnused( IOPacketQueue, 10);
48OSMetaClassDefineReservedUnused( IOPacketQueue, 11);
49OSMetaClassDefineReservedUnused( IOPacketQueue, 12);
50OSMetaClassDefineReservedUnused( IOPacketQueue, 13);
51OSMetaClassDefineReservedUnused( IOPacketQueue, 14);
52OSMetaClassDefineReservedUnused( IOPacketQueue, 15);
53
54
55//---------------------------------------------------------------------------
56// Lock macros
57
58#define LOCK     IOSimpleLockLock(_lock)
59#define UNLOCK   IOSimpleLockUnlock(_lock)
60
61//---------------------------------------------------------------------------
62// Initialize an IOPacketQueue object.
63
64bool IOPacketQueue::initWithCapacity(UInt32 capacity)
65{
66    if (super::init() == false)
67    {
68        IOLog("IOPacketQueue: super::init() failed\n");
69        return false;
70    }
71
72    _queue = IONew(IOMbufQueue, 1);
73    if (_queue == 0)
74        return false;
75
76    IOMbufQueueInit(_queue, capacity);
77
78    if ((_lock = IOSimpleLockAlloc()) == 0)
79        return false;
80
81    IOSimpleLockInit(_lock);
82
83    return true;
84}
85
86//---------------------------------------------------------------------------
87// Factory method that will construct and initialize an IOPacketQueue object.
88
89IOPacketQueue * IOPacketQueue::withCapacity(UInt32 capacity)
90{
91    IOPacketQueue * queue = new IOPacketQueue;
92
93    if (queue && !queue->initWithCapacity(capacity))
94    {
95        queue->release();
96        queue = 0;
97    }
98    return queue;
99}
100
101//---------------------------------------------------------------------------
102// Frees the IOPacketQueue instance.
103
104void IOPacketQueue::free()
105{
106    if (_lock)
107    {
108        IOSimpleLockFree(_lock);
109        _lock = 0;
110    }
111
112    if (_queue)
113    {
114        flush();
115        IODelete(_queue, IOMbufQueue, 1);
116        _queue = 0;
117    }
118
119    super::free();
120}
121
122//---------------------------------------------------------------------------
123// Get the current size of the queue.
124
125UInt32 IOPacketQueue::getSize() const
126{
127    return IOMbufQueueGetSize(_queue);
128}
129
130//---------------------------------------------------------------------------
131// Change the capacity of the queue.
132
133bool IOPacketQueue::setCapacity(UInt32 capacity)
134{
135    IOMbufQueueSetCapacity(_queue, capacity);
136    return true;
137}
138
139//---------------------------------------------------------------------------
140// Get the capacity of the queue.
141
142UInt32 IOPacketQueue::getCapacity() const
143{
144    return IOMbufQueueGetCapacity(_queue);
145}
146
147//---------------------------------------------------------------------------
148// Peek at the head of the queue without dequeueing the packet.
149
150const mbuf_t IOPacketQueue::peek() const
151{
152    return IOMbufQueuePeek(_queue);
153}
154
155//---------------------------------------------------------------------------
156// Add a packet chain to the head of the queue.
157
158void IOPacketQueue::prepend(mbuf_t m)
159{
160    IOMbufQueuePrepend(_queue, m);
161}
162
163void IOPacketQueue::prepend(IOPacketQueue * queue)
164{
165    IOMbufQueuePrepend(_queue, queue->_queue);
166}
167
168//---------------------------------------------------------------------------
169// Add a packet chain to the tail of the queue.
170
171bool IOPacketQueue::enqueue(mbuf_t m)
172{
173    return IOMbufQueueEnqueue(_queue, m);
174}
175
176bool IOPacketQueue::enqueue(IOPacketQueue * queue)
177{
178    return IOMbufQueueEnqueue(_queue, queue->_queue);
179}
180
181UInt32 IOPacketQueue::enqueueWithDrop(mbuf_t m)
182{
183    return IOMbufQueueEnqueue(_queue, m) ? 0 : IOMbufFree(m);
184}
185
186//---------------------------------------------------------------------------
187// Remove a single packet from the head of the queue.
188
189mbuf_t IOPacketQueue::dequeue()
190{
191    return IOMbufQueueDequeue(_queue);
192}
193
194//---------------------------------------------------------------------------
195// Remove all packets from the queue and return the chain of packet(s).
196
197mbuf_t IOPacketQueue::dequeueAll()
198{
199    return IOMbufQueueDequeueAll(_queue);
200}
201
202//---------------------------------------------------------------------------
203// Remove all packets from the queue and put them back to the free mbuf
204// pool. The size of the queue will be cleared to zero.
205
206UInt32 IOPacketQueue::flush()
207{
208    return IOMbufFree(IOMbufQueueDequeueAll(_queue));
209}
210
211//---------------------------------------------------------------------------
212// Locked forms of prepend/enqueue/dequeue/dequeueAll methods.
213// A spinlock will enforce mutually exclusive queue access.
214
215void IOPacketQueue::lockPrepend(mbuf_t m)
216{
217    LOCK;
218    IOMbufQueuePrepend(_queue, m);
219    UNLOCK;
220}
221
222bool IOPacketQueue::lockEnqueue(mbuf_t m)
223{
224    bool ok;
225    LOCK;
226    ok = IOMbufQueueEnqueue(_queue, m);
227    UNLOCK;
228    return ok;
229}
230
231UInt32 IOPacketQueue::lockEnqueueWithDrop(mbuf_t m)
232{
233    bool ok;
234    LOCK;
235    ok = IOMbufQueueEnqueue(_queue, m);
236    UNLOCK;
237    return ok ? 0 : IOMbufFree(m);
238}
239
240mbuf_t IOPacketQueue::lockDequeue()
241{
242    mbuf_t m;
243    LOCK;
244    m = IOMbufQueueDequeue(_queue);
245    UNLOCK;
246    return m;
247}
248
249mbuf_t IOPacketQueue::lockDequeueAll()
250{
251    mbuf_t m;
252    LOCK;
253    m = IOMbufQueueDequeueAll(_queue);
254    UNLOCK;
255    return m;
256}
257
258UInt32 IOPacketQueue::lockFlush()
259{
260    mbuf_t m;
261    LOCK;
262    m = IOMbufQueueDequeueAll(_queue);
263    UNLOCK;
264    return IOMbufFree(m);
265}
266