1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 34 35
36
37 import xdc.rov.ViewInfo;
38
39 import xdc.runtime.Error;
40 import xdc.runtime.Assert;
41 import xdc.runtime.IHeap;
42 import xdc.runtime.knl.Sync;
43 import xdc.runtime.knl.ISync;
44
45 import ti.sysbios.io.DEV;
46 import ti.sysbios.knl.Queue;
47
48 /*!
49 * ======== GIO ========
50 * General Purpose IO Manager.
51 *
52 * The GIO Manager offers both the issue/reclaim model and the read/write
53 * model to send and receive data from drivers that implement the IOM
54 * interface as provided in ti/sysbios/io/iom.h.
55 *
56 * In the issue/reclaim model, the client calls {@link #issue} when he has
57 * a buffer of data. issue() is non-blocking and returns -- it simply
58 * submits the buffer to the driver for I/O. The client calls
59 * {@link #reclaim} to get the buffer back. A call to reclaim() may block.
60 * Upon return from reclaim(), the client can re-use the buffer.
61 *
62 * The client can issue many buffers before reclaiming them.
63 * Buffers are always reclaimed in the order that they were issued.
64 * The client can optionally pass a user argument to issue(). This argument
65 * can be retrieved with reclaim().
66 *
67 * In the read/write model, clients will call {@link #read} or {@link #write}
68 * to send/receive data. Here the client may block until buffer is ready or
69 * a timeout occurs.
70 *
71 * The GIO module also provides {@link #control} to send down driver specific
72 * control commands. The {@link #abort} function can be used to abort any
73 * pending I/O.
74 *
75 * The {@link ti.sysbios.io.DEV} module maintains a name table of IOM drivers.
76 * This table is used by GIO to create an IO stack. The name passed to
77 * {@link #create} is usually of the form "/uart". This name may
78 * correspond to the following IO stack.
79 *
80 * GIO Instance
81 *
82 * |
83 * v
84 *
85 * IOM Instance (/uart)
86 *
87 * The GIO module uses the {@link xdc.runtime.knl.Sync} module for
88 * synchronization. GIO will call {@link xdc.runtime.knl.Sync#signal} when
89 * I/O completes and {@link xdc.runtime.knl.Sync#wait} to wait for I/O.
90 *
91 * By default the I/O manager will create a semaphore for synchronization
92 * if no sync handle is passed to {@link #create}.
93 */
94
95 @DirectCall
96 @InstanceFinalize
97 @InstanceInitError
98
99 module GIO
100 {
101 /*! Init function type definition. */
102 typedef Void (*InitFxn)();
103
104
105 const UInt INPUT = 0x1; /*! mode for input */
106 const UInt OUTPUT = 0x2; /*! mode for output */
107 const UInt INOUT = 0x3; /*! mode for input & output */
108
109 /*!
110 * Error raised when name not found in DeviceTable.
111 */
112 config Error.Id E_notFound = {
113 msg: "E_notFound: %s name not found"
114 };
115
116 /*!
117 * Error raised when driver's mdCreateChan() call fails
118 */
119 config Error.Id E_createFailed = {
120 msg: "E_createFailed: mdCreateChan returned error %d"
121 };
122
123 /*!
124 * Asserted in GIO_read(), GIO_write() if I/O model is not
125 * STANDARD or in GIO_issue(), GIO_reclaim(), or GIO_prime() if the
126 * I/O model is not ISSUERECLAIM.
127 */
128 config Assert.Id A_badModel = {
129 msg: "A_badModel: invalid use of API for current I/O model"
130 };
131
132 /*!
133 * ======== deviceTableSize ========
134 * This configuration parameter has been deprecated. Use DEV.tableSize.
135 */
136 config Int deviceTableSize = 8;
137
138 metaonly struct BasicView {
139 String label;
140 UInt freeCount;
141 UInt doneCount;
142 UInt submitCount;
143 String model;
144 String mode;
145 Bool userSuppliedSync;
146 }
147
148 @Facet
149 metaonly config ViewInfo.Instance rovViewInfo =
150 ViewInfo.create({
151 viewMap: [
152 ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic', structName: 'BasicView'}],
153 ]
154 });
155
156 /*! model for IO channel */
157 enum Model {
158 Model_STANDARD, /*! used for read, write, submit */
159 Model_ISSUERECLAIM /*! used for issue, reclaim, prime */
160 };
161
162 /*! application callback function used with GIO_submit() */
163 typedef Void (*TappCallBack)(Ptr, Int, Ptr, SizeT);
164
165 /*!
166 * Application Callback Structure.
167 *
168 * Used with GIO_submit() for asynchronous callback.
169 */
170 struct AppCallback {
171 TappCallBack fxn;
172 Ptr arg;
173 };
174
175 /*!
176 * ======== addDevice ========
177 * This API has been deprecated. Use DEV_create().
178 */
179 Int addDevice(String name, Ptr fxns, InitFxn initFxn, Int devid, Ptr params);
180
181 /*!
182 * ======== addDeviceMeta ========
183 * This API has been deprecated. Use DEV.create().
184 */
185 metaonly Void addDeviceMeta(String name, String fxns, String initFxn, Int devid, String params);
186
187 /*!
188 * ======== removeDevice ========
189 * This API has been deprecated. Use DEV_match() and DEV_delete().
190 */
191 Int removeDevice(String name);
192
193 instance:
194
195 /*!
196 * ======== model ========
197 * I/O model
198 *
199 * Set the model to STANDARD to use read(), write() and submit() APIs.
200 * Set the model to ISSUERECLAIM to use issue(), reclaim(), and
201 * prime() APIs.
202 *
203 * The default for this parameter is STANDARD.
204 */
205 config Model model = Model_STANDARD;
206
207 /*! Number of packets to use for asynchronous I/O */
208 config Int numPackets = 2;
209
210 /*! For blocking calls. Default is BIOS_WAIT_FOREVER */
211 config UInt timeout = ~(0);
212
213 /*! ISync handle used to signal IO completion */
214 config ISync.Handle sync = null;
215
216 /*!
217 * ======== chanParams ========
218 * channel parameters
219 *
220 * The chanParams parameter is a pointer that may be used to pass device
221 * or domain-specific arguments to the mini-driver. The contents at the
222 * specified address are interpreted by the mini-driver in a
223 * device-specific manner.
224 */
225 config Ptr chanParams = null;
226
227 /*!
228 * ======== packets ========
229 * The address of the buffer used for IOM packets.
230 *
231 * If set to 'null', the packets will be allocated from the heap
232 * during runtime, otherwise the user may set this to a buffer of their
233 * creation to be used for the IOM packets.
234 *
235 * The packets will be split into
236 * {@link ti.sysbios.io.GIO#numPackets} each the size of IOM_Packet.
237 *
238 * Please note that if the packets is user supplied, then it is the user's
239 * responsibility to ensure that it is aligned properly and is also large
240 * enough to contain {@link ti.sysbios.io.GIO#numPackets} number of
241 * IOM_Packet packets. The size of packets buffer, if provided,
242 * should be
243 *
244 * @p(code)
245 * sizeof(IOM_Packet) * numPackets
246 * @p
247 *
248 * Example:
249 * @p(code)
250 * #define NUMPACKETS 2
251 * IOM_Packet inPackets[NUMPACKETS];
252 *
253 * GIO_Params params;
254 *
255 * GIO_Params_init(¶ms);
256 * params.numPackets = NUMPACKETS;
257 * params.packets = inPackets;
258 * @p
259 */
260 config Ptr packets = null;
261
262 /*!
263 * ======== abort ========
264 * Abort all pending IO.
265 *
266 * An application calls GIO_abort to abort all input and output from
267 * the device. When this call is made, all pending calls are completed
268 * with a status of GIO_ABORTED. An application uses this call to
269 * return the device to its initial state. Usually this is done in
270 * response to an unrecoverable error at the device level.
271 *
272 * GIO_abort returns IOM_COMPLETED upon successfully aborting all
273 * input and output requests. If an error occurs, the device returns a
274 * negative value. The list of error values are defined in the
275 * ti/sysbios/io/iom.h file.
276 *
277 * A call to GIO_abort results in a call to the mdSubmit function of the
278 * associated mini-driver. The IOM_ABORT command is passed to the
279 * mdSubmit function. The mdSubmit call is typically a blocking call, so
280 * calling GIO_abort can result in the thread blocking.
281 *
282 * If using ISSUERECLAIM IO model, the the underlying device
283 * connected to stream is idled as a result of calling abort and
284 * all buffers are ready for reclaim(). The client needs to call
285 * {@link #reclaim} to get back the buffers. However the client will
286 * NOT block when calling reclaim() after an abort().
287 *
288 * @b(returns) IOM_COMPLETED on success, < 0 on failure
289 */
290 Int abort();
291
292 /*!
293 * ======== control ========
294 * Send a control command to the driver.
295 *
296 * An application calls GIO_control to configure or perform control
297 * functionality on the communication channel.
298 *
299 * The cmd parameter may be one of the command code constants listed in
300 * ti/sysbios/io/iom.h. A mini-driver may add command codes for
301 * additional functionality.
302 *
303 * The args parameter points to a data structure defined by the device to
304 * allow control information to be passed between the device and the
305 * application. This structure can be generic across a domain or
306 * specific to a mini-driver. In some cases, this argument may point
307 * directly to a buffer holding control data. In other cases, there
308 * may be a level of indirection if the mini-driver expects a data
309 * structure to package many components of data required for the control
310 * operation. In the simple case where no data is required, this
311 * parameter may just be a predefined command value.
312 *
313 * GIO_control returns IOM_COMPLETED upon success. If an error occurs,
314 * the device returns a negative value. For a list of error values, see
315 * ti/sysbios/io/iom.h. A call to GIO_control results in a call to
316 * the mdControl function of the associated mini-driver. The mdControl
317 * call is typically a blocking call, so calling GIO_control can result
318 * in blocking.
319 *
320 * @param(cmd) device specific command
321 * @param(args) pointer to device-specific arguments
322 * @b(returns) IOM_COMPLETED on success, < 0 on failure
323 */
324 Int control(UInt cmd, Ptr args);
325
326 /*!
327 * ======== create ========
328 * Create a GIO Instance.
329 *
330 * An application calls GIO_create to create a GIO_Obj object and open
331 * a communication channel. This function initializes the I/O channel
332 * and opens the lower-level device driver channel. The GIO_create call
333 * also creates the synchronization objects it uses and stores them in
334 * the GIO_Obj object.
335 *
336 * The name argument is the name specified for the device when it was
337 * created in the configuration or at runtime.
338 *
339 * The mode argument specifies the mode in which the device is to be
340 * opened. This may be IOM_INPUT, IOM_OUTPUT, or IOM_INOUT.
341 *
342 * If the status returned by the device is non-NULL, a status value is
343 * placed at the address specified by the status parameter.
344 *
345 * The GIO_create call allocates a list of IOM_Packet items as specified
346 * by the numPackets member of the params structure and stores them in
347 * the GIO_Obj object it creates.
348 *
349 * @param(name) name that identifies the IO stack
350 * @param(mode) mode of channel
351 */
352 create(String name, UInt mode);
353
354 /*!
355 * ======== flush ========
356 * Drain output buffers and discard any pending input
357 *
358 * An application calls GIO_flush to flush the input and output
359 * channels of the device. All input data is discarded; all pending
360 * output requests are completed. When this call is made, all pending
361 * input calls are completed with a status of IOM_FLUSHED, and all
362 * output calls are completed routinely.
363 *
364 * This call returns IOM_COMPLETED upon successfully flushing all
365 * input and output. If an error occurs, the device returns a negative
366 * value. For a list of error values, see ti/sysbios/io/iom.h.
367 *
368 * A call to GIO_flush results in a call to the mdSubmit function of
369 * the associated mini-driver. The IOM_FLUSH command is passed to the
370 * mdSubmit function. The mdSubmit call is typically a blocking call,
371 * so calling GIO_flush can result in the thread blocking while waiting
372 * for output calls to be completed.
373 *
374 * @b(returns) IOM_COMPLETED on success, < 0 on failure
375 */
376 Int flush();
377
378 /*!
379 * ======== issue ========
380 * Issue a buffer to the stream.
381 *
382 * This function issues a buffer to the stream for IO. This API is
383 * non-blocking.
384 *
385 * Failure of issue() indicates that the stream was not able to accept the
386 * buffer being issued or that there was a error from the underlying
387 * driver. Note that the error could be driver specific.
388 * If issue() fails because of an underlying driver problem
389 * {@link #abort} should be called before attempting more I/O through the
390 * stream.
391 *
392 * The interpretation of the logical size of a buffer, is direction
393 * dependent. For a stream opened in OUTPUT mode, the logical size
394 * of the buffer indicates the number of minimum addressable units of of
395 * data it contains.
396 *
397 * For a stream opened in INPUT mode, the logical size
398 * of a buffer indicates the number of minimum addressable units being
399 * requested by the client. In either case, the logical size of the buffer
400 * must be less than or equal to the physical size of the buffer.
401 *
402 * issue() is used in conjunction with {@link #reclaim}. The issue() call
403 * sends a buffer to a stream, and reclaim() retrieves a buffer
404 * from a stream. In normal operation each issue() call is followed by an
405 * reclaim() call.
406 *
407 * Short bursts of multiple issue() calls can be made without an
408 * intervening reclaim() call followed by short bursts of reclaim() calls,
409 * but over the life of the stream issue() and reclaim() must be called
410 * the same number of times. The number of issue() calls can exceed the
411 * number of reclaim() calls by {@link #maxIssues}.
412 *
413 * The client argument is not interpreted by IO or the underlying
414 * modules, but is offered as a service to the stream client. All compliant
415 * device drivers preserve the value of arg and maintain its association
416 * with the data that it was issued with. arg provides a method for a
417 * client to associate additional information with a particular buffer of
418 * data. The arg is returned during reclaim().
419 *
420 * @param(buf) buffer pointer
421 * @param(size) size of buffer
422 * @param(arg) application arg
423 * @b(returns) IOM_COMPLETED on success, < 0 on failure
424 *
425 */
426 Int issue(Ptr buf, SizeT size, UArg arg);
427
428 /*!
429 * ======== reclaim ========
430 * Reclaim a buffer that was previously issued by calling {@link #issue}.
431 *
432 * reclaim() is used to request a buffer back from a stream.
433 *
434 * If a stream was created in OUTPUT mode, then reclaim() returns a
435 * processed buffer, and size is zero. If a stream was opened in
436 * INPUT mode, reclaim() returns a full buffer, and size is the number
437 * of minimum addressable units of data in the buffer.
438 *
439 * reclaim() calls Sync_wait() with the timeout specified when the
440 * channel was created. For the default SyncSem, reclaim() blocks
441 * until a buffer can be returned to the caller, or until a timeout occurs.
442 *
443 * Failure of reclaim() indicates that no buffer was returned to
444 * the client. Therefore, if reclaim() fails, the client should
445 * not attempt to de-reference pBuf, since it is not guaranteed to contain
446 * a valid buffer pointer.
447 *
448 * reclaim() is used in conjunction with {@link #issue} to operate
449 * a stream. The issue() call sends a buffer to a stream, and
450 * reclaim() retrieves a buffer from a stream. In normal operation
451 * each issue call is followed by an reclaim call.
452 *
453 * Short bursts of multiple issue() calls can be made without an
454 * intervening reclaim() call followed by short bursts of reclaim() calls,
455 * but over the life of the stream issue() and reclaim() must be called
456 * the same number of times. The number of issue() calls can exceed the
457 * number of reclaim() calls by {@link #maxIssues}.
458 *
459 * A reclaim() call should not be made without at least one
460 * outstanding issue() call. Calling reclaim() with no
461 * outstanding issue() calls results in an error {@link #E_noBuffersIssued}
462 *
463 * reclaim() only returns buffers that were passed in using issue(). It
464 * also returns the buffers in the same order that they were issued.
465 *
466 * reclaim() returns the size transferred in case of success.
467 * It returns zero when an error is caught. In case of timeout, the error
468 * is {@link #E_timeout}.
469 *
470 * @param(pBuf) returned buffer pointer
471 * @param(pSize) pointer to size of buffer (OUTPUT parameter)
472 * @param(pArg) pointer to client arg. Can be null.
473 * @b(returns) IOM_COMPLETED on success, < 0 on failure
474 *
475 */
476 Int reclaim(Ptr *pBuf, SizeT *pSize, UArg *pArg);
477
478 /*!
479 * ======== read ========
480 * Synchronous read command
481 *
482 * An application calls GIO_read to read a specified number of MADUs
483 * (minimum addressable data units) from the communication channel.
484 *
485 * The buf parameter points to a device-defined data structure for
486 * passing buffer data between the device and the application. This
487 * structure may be generic across a domain or specific to a single
488 * mini-driver. In some cases, this parameter may point directly to a
489 * buffer that holds the read data. In other cases, this parameter may
490 * point to a structure that packages buffer information, size, offset
491 * to be read from, and other device-dependent data. For example, for
492 * video capture devices this structure may contain pointers to RGB
493 * buffers, their sizes, video format, and a host of data required for
494 * reading a frame from a video capture device. Upon a successful read,
495 * this argument points to the returned data.
496 *
497 * The pSize parameter points to the size of the buffer or data
498 * structure pointed to by the buf parameter. When the function
499 * returns, this parameter points to the number of MADUs read from the
500 * device. This parameter is relevant only if the buf parameter points
501 * to a raw data buffer. In cases where it points to a device-defined
502 * structure it is redundant -- the size of the structure is known to
503 * the mini-driver and the application. At most, it can be used for
504 * error checking.
505 *
506 * GIO_read returns IOM_COMPLETED upon successfully reading the
507 * requested number of MADUs from the device. If an error occurs,
508 * the device returns a negative value. For a list of error values,
509 * see ti/sybios/io/iom.h.
510 *
511 * A call to GIO_read results in a call to the mdSubmit function of
512 * the associated mini-driver. The IOM_READ command is passed to the
513 * mdSubmit function. The mdSubmit call is typically a blocking call,
514 * so calling GIO_read can result in the thread blocking.
515 *
516 * @param(buf) buffer pointer
517 * @param(pSize) pointer to size of buffer (INPUT/OUTPUT parameter)
518 * @b(returns) IOM_COMPLETED on success, < 0 on failure
519 */
520 Int read(Ptr buf, SizeT *pSize);
521
522 /*!
523 * ======== write ========
524 * Synchronous write command
525 *
526 * An application calls GIO_write to write a specified number of MADUs
527 * (minimum addressable data units) from the communication channel.
528 *
529 * The buf parameter points to a device-defined data structure for
530 * passing buffer data between the device and the application. This
531 * structure may be generic across a domain or specific to a single
532 * mini-driver. In some cases, this parameter may point directly to a
533 * buffer that holds the write data. In other cases, this parameter may
534 * point to a structure that packages buffer information, size, offset
535 * to be write from, and other device-dependent data. For example, for
536 * video capture devices this structure may contain pointers to RGB
537 * buffers, their sizes, video format, and a host of data required for
538 * reading a frame from a video capture device.
539 *
540 * The pSize parameter points to the size of the buffer or data
541 * structure pointed to by the buf parameter. When the function
542 * returns, this parameter points to the number of MADUs written to the
543 * device. This parameter is relevant only if the buf parameter points
544 * to a raw data buffer. In cases where it points to a device-defined
545 * structure it is redundant -- the size of the structure is known to
546 * the mini-driver and the application. At most, it can be used for
547 * error checking.
548 *
549 * GIO_write returns IOM_COMPLETED upon successfully writing the
550 * requested number of MADUs from the device. If an error occurs,
551 * the device returns a negative value. For a list of error values,
552 * see ti/sybios/io/iom.h.
553 *
554 * A call to GIO_write results in a call to the mdSubmit function of
555 * the associated mini-driver. The IOM_WRITE command is passed to the
556 * mdSubmit function. The mdSubmit call is typically a blocking call,
557 * so calling GIO_write can result in the thread blocking.
558 *
559 * @param(buf) buffer pointer
560 * @param(pSize) pointer to size of buffer (INPUT/OUTPUT parameter)
561 * @b(returns) IOM_COMPLETED on success, < 0 on failure
562 */
563 Int write(Ptr buf, SizeT *pSize);
564
565 /*!
566 * ======== submit ========
567 * Submit an IO job to the mini-driver
568 *
569 * GIO_submit is not typically called by applications. Instead, it is
570 * used internally and for user-defined extensions to the GIO module.
571 *
572 * The cmd parameter is IOM_READ, IOM_WRITE, IOM_ABORT or IOM_FLUSH
573 * when used internally. A mini driver may add command codes for
574 * additional functionality.
575 *
576 * The bufp parameter points to a device-defined data structure for
577 * passing buffer data between the device and the application. This
578 * structure may be generic across a domain or specific to a single
579 * mini-driver. In some cases, this parameter may point directly to
580 * a buffer that holds the data. In other cases, this parameter may
581 * point to a structure that packages buffer information, size, offset
582 * to be read from, and other device-dependent data.
583 *
584 * The pSize parameter points to the size of the buffer or data structure
585 * pointed to by the bufp parameter. When the function returns, this
586 * parameter points to the number of MADUs transferred to or from the
587 * device. This parameter is relevant only if the bufp parameter points
588 * to a raw data buffer. In cases where it points to a device-defined
589 * structure it is redundant -- the size of the structure is known to
590 * the mini-driver and the application. At most, it can be used for
591 * error checking.
592 *
593 * The appCallback parameter points to either a callback structure that
594 * contains the callback function to be called when the request completes.
595 * queued request is completed, the callback routine (if specified) is
596 * invoked (i.e. blocking). If the appCallback parameter is NULL, then
597 * the call to GIO_submit() will be synchronous and will not return
598 * until IO is complete (or an error occurs).
599 *
600 * GIO_submit returns IOM_COMPLETED upon successfully carrying out
601 * the requested functionality. If the request is queued, then a status of
602 * IOM_PENDING is returned. If an error occurs, the device returns a
603 * negative value. For a list of error values, see ti/sysbios/io/iom.h.
604 *
605 * A call to GIO_submit results in a call to the mdSubmit function of
606 * the associated mini-driver. The specified command is passed to the
607 * mdSubmit function.
608 *
609 * @param(cmd) driver specific packet command
610 * @param(buf) buffer pointer
611 * @param(pSize) pointer to size of buffer (INPUT/OUTPUT parameter)
612 * @param(appCallBack) pointer to application callback structure
613 * @b(returns) IOM_COMPLETED on success, < 0 on failure
614 */
615 Int submit(UInt cmd, Ptr buf, SizeT *pSize, AppCallback *appCallback);
616
617 /*!
618 * ======== prime ========
619 * Prime an OUTPUT stream instance.
620 *
621 * This API facilitates buffering of an output channel. Consider a
622 * task that constantly gets data from input channel and sends to an
623 * output channel. To start with it may want to issue buffers to the
624 * input channel and output channel to enable double buffering.
625 * For an input channel there is no problem. For an output channel however
626 * the buffer data is sent out through the peripheral and in the case of a
627 * heterogenous system, the data will be sent to the other processor.
628 *
629 * In such cases where the driver cannot handle dummy buffers,
630 * IO_prime can be used to make buffers available instantly for
631 * reclaim without actually sending the buffers to the driver.
632 * This API is non-blocking.
633 *
634 * The primary use of prime() is used when applications want to prime
635 * an output channel at startup, without sending data to the driver.
636 * This allows them to reclaim and issue in their task.
637 *
638 * Failure of prime() indicates that the stream was not able to accept the
639 * buffer being issued due to un-avaibailibity of IO packets.
640 *
641 * The client argument is not interpreted by IO.
642 *
643 * @param(buf) buffer pointer
644 * @param(size) size of buffer
645 * @param(arg) app arg
646 * @b(returns) IOM_COMPLETED on success, < 0 on failure
647 */
648 Int prime(Ptr buf, SizeT size, UArg arg);
649
650 internal:
651
652
653 struct Instance_State {
654 String name;
655 UInt mode;
656 UInt model;
657 UInt timeout;
658 IHeap.Handle packetHeap;
659 ISync.Handle sync;
660 Bool userSync;
661 Bool userPackets;
662 Queue.Object doneList;
663 Queue.Object freeList;
664 Ptr packets;
665 Int numPackets;
666 Int freeCount;
667 Int doneCount;
668 Int submitCount;
669
670 Ptr fxns;
671 Ptr mdChan;
672 };
673 }