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#ifndef _IOBASICOUTPUTQUEUE_H
24#define _IOBASICOUTPUTQUEUE_H
25
26#include <IOKit/IOLocks.h>
27#include <IOKit/network/IOOutputQueue.h>
28#include <IOKit/network/IOPacketQueue.h>
29
30struct IOMbufQueue;
31
32/*! @class IOBasicOutputQueue
33    @abstract A concrete implementation of an IOOutputQueue.
34    @discussion This object uses a mutex to protect the packet queue from
35    multiple producers.
36    A single producer is promoted to become a consumer when the queue is
37    not active. Otherwise, the producer will simply queue the packet and
38    return without blocking.
39
40    The flow of packets from the queue to its target can be controlled
41    by calling methods such as start(), stop(), or service(). The target
42    is expected to call those methods from a single threaded context,
43    i.e. the work loop context in a network driver. In addition, the
44    target must also return a status for every packet delivered by the
45    consumer thread. This return value is the only mechanism that the
46    target can use to manage the queue when it is running on the
47    consumer thread.
48*/
49
50class IOBasicOutputQueue : public IOOutputQueue
51{
52    OSDeclareDefaultStructors( IOBasicOutputQueue )
53
54private:
55	static IOReturn dispatchNetworkDataNotification(void *          target,
56                                                    void *          param,
57                                                    IONetworkData * data,
58                                                    UInt32          type);
59
60    void dequeue();
61
62protected:
63    OSObject *            _target;
64    IOOutputAction        _action;
65    UInt32                _priorities;
66    IOOutputQueueStats *  _stats;
67    IONetworkData *       _statsData;
68	IOLock *              _queueLock;
69    IOMbufQueue *         _inQueues;
70    IOMbufQueue *         _primaryQueues;
71    IOMbufQueue *         _shadowQueues;
72    volatile bool         _waitDequeueDone;
73    volatile UInt32       _state;
74    volatile UInt32       _serviceCount;
75
76/*! @function serviceThread
77    @abstract Provides an implementation for the serviceThread() method
78    defined in IOOutputQueue.
79    @discussion This method is called by the scheduled service thread when it
80    starts to run. The service thread is scheduled by service()
81    to restart a stalled queue when the kServiceAsync option is given.
82    @param param A parameter that was given to scheduleServiceThread().
83    This parameter is not used.
84*/
85
86    virtual void serviceThread(void * param);
87
88/*! @function output
89    @abstract Transfers all packets in the mbuf queue to the target.
90    @param queue A queue of output packets.
91    @param state Returns a state bit defined by IOBasicOutputQueue that
92    declares the new state of the queue following this method call.
93    A kStateStalled is returned if the queue should stall, otherwise 0
94    is returned.
95*/
96
97    virtual void output(IOMbufQueue * queue, UInt32 * state);
98
99/*! @function free
100    @abstract Frees the IOBasicOutputQueue object.
101    @discussion This function releases allocated resources, then call super::free().
102*/
103
104    virtual void free();
105
106/*! @function handleNetworkDataAccess
107    @abstract Handles an external access to the IONetworkData object
108    returned by getStatisticsData().
109    @param data The IONetworkData object being accessed.
110    @param type Description of the type of access being performed.
111    @param param An optional parameter for the handler.
112    @result Returns kIOReturnSuccess on success, or an error code otherwise.
113*/
114
115    virtual IOReturn handleNetworkDataAccess(IONetworkData * data,
116                                             UInt32          type,
117                                             void *          param);
118
119public:
120
121/*! @function init
122    @abstract Initializes an IOBasicOutputQueue object.
123    @param target The object that will handle packets removed from the
124    queue, which is usually a subclass of IONetworkController.
125    @param action The function that will handle packets removed from the
126    queue.
127    @param capacity The initial capacity of the output queue.
128    @result Returns true if initialized successfully, false otherwise.
129*/
130
131    virtual bool init(OSObject *     target,
132                      IOOutputAction action,
133                      UInt32         capacity = 0,
134                      UInt32         priorities = 1);
135
136/*! @function withTarget
137    @abstract Factory method that constructs and initializes an
138    IOBasicOutputQueue object.
139    @param target An IONetworkController object that will handle packets
140    removed from the queue.
141    @param capacity The initial capacity of the output queue.
142    @result Returns an IOBasicOutputQueue object on success, or 0 otherwise.
143*/
144
145    static IOBasicOutputQueue * withTarget(IONetworkController * target,
146                                           UInt32                capacity = 0);
147
148    /*! @function withTarget
149     @abstract Factory method that constructs and initializes an
150     IOBasicOutputQueue object.
151     @param target An IONetworkController object that will handle packets
152     removed from the queue.
153     @param capacity The initial capacity of the output queue.
154     @param priorities The number of traffic priorities supported
155     @result Returns an IOBasicOutputQueue object on success, or 0 otherwise.
156     */
157
158    static IOBasicOutputQueue * withTarget(IONetworkController * target,
159                                           UInt32                capacity,
160                                           UInt32                priorities);
161
162/*! @function withTarget
163    @abstract Factory method that constructs and initializes an
164    IOBasicOutputQueue object.
165    @param target The object that will handle packets removed from the
166    queue.
167    @param action The function that will handle packets removed from the
168    queue.
169    @param capacity The initial capacity of the output queue.
170    @result Returns an IOBasicOutputQueue object on success, or 0 otherwise.
171*/
172
173    static IOBasicOutputQueue * withTarget(OSObject *     target,
174                                           IOOutputAction action,
175                                           UInt32         capacity = 0);
176
177    /*! @function withTarget
178     @abstract Factory method that constructs and initializes an
179     IOBasicOutputQueue object.
180     @param target The object that will handle packets removed from the
181     queue.
182     @param action The function that will handle packets removed from the
183     queue.
184     @param capacity The initial capacity of the output queue.
185     @param priorities The number of traffic priorities supported
186     @result Returns an IOBasicOutputQueue object on success, or 0 otherwise.
187     */
188
189    static IOBasicOutputQueue * withTarget(OSObject *     target,
190                                           IOOutputAction action,
191                                           UInt32         capacity,
192                                           UInt32         priorities);
193
194/*! @function enqueue
195    @abstract Adds a packet, or a chain of packets,
196    to the queue.
197    @discussion This method is called by a client to add a packet, or a chain of packets,
198    to the queue.  A packet is described by an mbuf chain, while a chain
199    of packets is constructed by linking multiple mbuf chains via the
200    m_nextpkt field. This method can be called by multiple client
201    threads.
202    @param m A single packet, or a chain of packets.
203    @param param A parameter provided by the caller.
204    @result Always returns 0.
205*/
206
207    virtual UInt32 enqueue(mbuf_t m, void * param);
208
209/*! @function start
210    @abstract Starts up the packet flow between the queue and its target.
211    @discussion Called by the target to start the queue. This will allow
212    packets to be removed from the queue, and then delivered to the target.
213    @result Returns true if the queue was started successfully, false otherwise. */
214
215    virtual bool start();
216
217/*! @function stop
218    @abstract Stops the packet flow between the queue and its target.
219    @discussion This method stops the queue and prevents it from sending packets to its
220    target. This call is synchronous and it may block. After this method
221    returns, the queue will no longer call the registered target/action,
222    even as new packets are added to the queue. The queue will continue to
223    absorb new packets until the size of the queue reaches its capacity.
224    The registered action must never call stop(), or a deadlock will occur.
225    @result Returns the previous running state of the queue,
226    true if the queue was running, false if the queue was already stopped.
227*/
228
229    virtual bool stop();
230
231/*! @enum ServiceAsync
232    @abstract The option bits recognized by service().
233    @constant kServiceAsync Set this option to service the queue in
234    an asynchronous manner. The service() call will not block, but a
235    scheduling latency will be introduced before the queue is serviced.
236*/
237
238    enum {
239        kServiceAsync = 0x1
240    };
241
242/*! @function service
243    @abstract Services a queue that was stalled by the target.
244    @discussion A target that stalls the queue must call service() when
245    it becomes ready to accept more packets. Calling this method when the
246    queue is not stalled is harmless.
247    @result Returns true if the queue was stalled and there were packets sitting in
248    the queue awaiting delivery, false otherwise.
249*/
250
251    virtual bool service(IOOptionBits options = 0);
252
253/*! @function flush
254    @abstract Drops and frees all packets currently held by the queue.
255    @discussion To ensure that all packets are removed from the queue,
256    stop() should be called prior to flush(), to make sure there are
257    no packets in-flight and being delivered to the target.
258    @result Returns the number of packets that were dropped and freed.
259*/
260
261    virtual UInt32 flush();
262
263/*! @function setCapacity
264    @abstract Changes the number of packets that the queue can hold
265    before it begins to drop excess packets.
266    @param capacity The new desired capacity.
267    @result Returns true if the new capacity was accepted, false otherwise.
268*/
269
270    virtual bool setCapacity(UInt32 capacity);
271
272/*! @function getCapacity
273    @abstract Gets the number of packets that the queue can hold.
274    @discussion The queue will begin to drop incoming packets when the
275    size of the queue reaches its capacity.
276    @result Returns the current queue capacity.
277*/
278
279    virtual UInt32 getCapacity() const;
280
281/*! @function getSize
282    @abstract Gets the number of packets currently held in the queue.
283    @result Returns the size of the queue.
284*/
285
286    virtual UInt32 getSize() const;
287
288/*! @function getDropCount
289    @abstract Gets the number of packets dropped by the queue.
290    @result Returns the number of packets dropped due to over-capacity, or by
291    external calls to the flush() method.
292*/
293
294    virtual UInt32 getDropCount();
295
296/*! @function getOutputCount
297    @abstract Gets the number of packets accepted by the target.
298    @result Returns the number of times that kIOOutputStatusAccepted is returned by
299    the target.
300*/
301
302    virtual UInt32 getOutputCount();
303
304/*! @function getRetryCount
305    @abstract Gets the number of instances when the target has refused to
306    accept the packet provided.
307    @result Returns the number of times that kIOOutputStatusRetry is returned by the
308    target.
309*/
310
311    virtual UInt32 getRetryCount();
312
313/*! @function getStallCount
314    @abstract Gets the number of instances when the target has stalled the
315    queue.
316    @result Returns the number of times that kIOOutputCommandStall is returned by the
317    target.
318*/
319
320    virtual UInt32 getStallCount();
321
322/*! @enum GetStateBits
323    @abstract The bits in the value returned by getState().
324    @constant kStateRunning Set when the queue is running. Calling start()
325    and stop() will set or clear this bit.
326    @constant kStateStalled Set when the queue is stalled by the target.
327    @constant kStateActive  Set when a consumer thread is actively removing
328    packets from the queue and passing them to the target.
329*/
330
331    enum {
332        kStateRunning            = 0x1,
333        kStateOutputStalled      = 0x2,
334        kStateOutputActive       = 0x4,
335        kStateOutputServiceMask  = 0xff00
336    };
337
338/*! @function getState
339    @abstract Gets the state of the queue object.
340    @result Returns the current state of the queue object.
341*/
342
343    virtual UInt32 getState() const;
344
345/*! @function getStatisticsData
346    @abstract Returns an IONetworkData object containing statistics counters
347    updated by the queue.
348    @result Returns an IONetworkData object.
349*/
350
351	virtual IONetworkData * getStatisticsData() const;
352};
353
354#endif /* !_IOBASICOUTPUTQUEUE_H */
355