summaryrefslogtreecommitdiff
path: root/drivers/mxc/security/sahara2/include/portable_os.h
blob: 445acd5d420c862530ef5f91e4014a62b232ea36 (plain)
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
/*
 * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
 */

/*
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

#ifndef PORTABLE_OS_H
#define PORTABLE_OS_H

/***************************************************************************/

/*
 * Add support for your target OS by checking appropriate flags and then
 * including the appropriate file.  Don't forget to document the conditions
 * in the later documentation section at the beginning of the
 * DOXYGEN_PORTABLE_OS_DOC.
 */

#if defined(LINUX_KERNEL)

#include "linux_port.h"

#elif defined(PORTABLE_OS)

#include "check_portability.h"

#else

#error Target OS unsupported or unspecified

#endif


/***************************************************************************/

/*!
 * @file portable_os.h
 *
 * This file should be included by portable driver code in order to gain access
 * to the OS-specific header files.  It is the only OS-related header file that
 * the writer of a portable driver should need.
 *
 * This file also contains the documentation for the common API.
 *
 * Begin reading the documentation for this file at the @ref index "main page".
 *
 */

/*!
 * @if USE_MAINPAGE
 * @mainpage Generic OS API for STC Drivers
 * @endif
 *
 * @section intro_sec Introduction
 *
 * This defines the API / kernel programming environment for portable drivers.
 *
 * This API is broken up into several functional areas.  It greatly limits the
 * choices of a device-driver author, but at the same time should allow for
 * greater portability of the resulting code.
 *
 * Each kernel-to-driver function (initialization function, interrupt service
 * routine, etc.) has a 'portable signature' which must be used, and a specific
 * function which must be called to generate the return statement.  There is
 * one exception, a background task or "bottom half" routine, which instead has
 * a specific structure which must be followed.  These signatures and function
 * definitions are found in @ref drsigs.
 *
 * None of these kernel-to-driver functions seem to get any arguments passed to
 * them.  Instead, there are @ref drsigargs which allow one of these functions
 * to get at fairly generic parts of its calling arguments, if there are any.
 *
 * Almost every driver will have some need to call the operating system
 * @ref dkops is the list of services which are available to the driver.
 *
 *
 * @subsection warn_sec Warning
 *
 * The specifics of the types, values of the various enumerations
 * (unless specifically stated, like = 0), etc., are only here for illustrative
 * purposes.  No attempts should be made to make use of any specific knowledge
 * gleaned from this documentation.  These types are only meant to be passed in
 * and out of the API, and their contents are to be handled only by the
 * provided OS-specific functions.
 *
 * Also, note that the function may be provided as macros in some
 * implementations, or vice versa.
 *
 *
 * @section dev_sec Writing a Portable Driver
 *
 * First off, writing a portable driver means calling no function in an OS
 * except what is available through this header file.
 *
 * Secondly, all OS-called functions in your driver must be invoked and
 * referenced through the signature routines.
 *
 * Thirdly, there might be some rules which you can get away with ignoring or
 * violating on one OS, yet will cause your code not to be portable to a
 * different OS.
 *
 *
 * @section limit_sec Limitations
 *
 * This API is not expected to handle every type of driver which may be found
 * in an operating system.  For example, it will not be able to handle the
 * usual design for something like a UART driver, where there are multiple
 * logical devices to access, because the design usually calls for some sort of
 * indication to the #OS_DEV_TASK() function or OS_DEV_ISR() to indicate which
 * channel is to be serviced by that instance of the task/function.  This sort
 * of argument is missing in this API for functions like os_dev_schedule_task() and
 * os_register_interrupt().
 *
 *
 * @section port_guide Porting Guidelines
 *
 * This section is intended for a developer who needs to port the header file
 * to an operating system which is not yet supported.
 *
 * This interface allows for a lot of flexibility when it comes to porting to
 * an operating systems device driver interface.  There are three main areas to
 * examine:  The use of Driver Routine Signatures, the use of Driver Argument
 * Access functions, the Calls to Kernel Functions, and Data Types.
 *
 *
 * @subsection port_sig Porting Driver Routine Signatures
 *
 * The three macros for each function (e.g. #OS_DEV_INIT(), #OS_DEV_INIT_DCL(),
 * and #OS_DEV_INIT_REF()) allow the flexibility of having a 'wrapper' function
 * with the OS-required signature, which would then call the user's function
 * with some different signature.
 *
 * The first form would lay down the wrapper function, followed by the
 * signature for the user function.  The second form would lay down just the
 * signatures for both functions, and the last function would reference the
 * wrapper function, since that is the interface function called by the OS.
 *
 * Note that the driver author has no visibility at all to the signature of the
 * routines.  The author can access arguments only through a limited set of
 * functions, and must return via another function.
 *
 * The Return Functions allow a lot of flexibility in converting the return
 * value, or not returning a value at all.  These will likely be implemented as
 * macros.
 *
 *
 * @subsection port_arg Porting Driver Argument Access Functions
 *
 * The signatures defined by the guide will usually be replaced with macro
 * definitions.
 *
 *
 * @subsection port_dki Porting Calls to Kernel Functions
 *
 * The signatures defined by the guide may be replaced with macro definitions,
 * if that makes more sense.
 *
 * Implementors are free to ignore arguments which are not applicable to their
 * OS.
 *
 * @subsection port_datatypes Porting Data Types
 *
 *
 */

/***************************************************************************
 * Compile flags
 **************************************************************************/

/*
 * This compile flag should only be turned on when running doxygen to generate
 * the API documentation.
 */
#ifdef DOXYGEN_PORTABLE_OS_DOC

/*!
 * @todo module_init()/module_cleanup() for Linux need to be added to OS
 * abstractions.  Also need EXPORT_SYMBOL() equivalent??
 *
 */

/* Drop OS differentation documentation here */

/*!
 * \#define this flag to build your driver as a Linux driver
 */
#define LINUX

/* end OS differentation documentation */

/*!
 * Symbol to give version number of the implementation file.  Earliest
 * definition is in version 1.1, with value 101 (to mean version 1.1)
 */
#define PORTABLE_OS_VERSION 101

/*
 * NOTICE: The following definitions (the rest of the file) are not meant ever
 * to be compiled.  Instead, they are the documentation for the portable OS
 * API, to be used by driver writers.
 *
 * Each individual OS port will define each of these types, functions, or
 * macros as appropriate to the target OS. This is why they are under the
 * DOXYGEN_PORTABLE_OS_DOC flag.
 */

/***************************************************************************
 * Type definitions
 **************************************************************************/

/*!
 * Type used for registering and deregistering interrupts.
 *
 * This is typically an interrupt channel number.
 */
typedef int os_interrupt_id_t;

/*!
 * Type used as handle for a process
 *
 * See #os_get_process_handle() and #os_send_signal().
 */
typedef int os_process_handle_t;

/*!
 * Generic return code for functions which need such a thing.
 *
 * No knowledge should be assumed of the value of any of these symbols except
 * that @c OS_ERROR_OK_S is guaranteed to be zero.
 *
 * @todo Any other named values? What about (-EAGAIN?  -ERESTARTSYS? Are they
 * too Linux/Unix-specific read()/write() return values) ?
 */
typedef enum {
	OS_ERROR_OK_S = 0,	/*!< Success  */
	OS_ERROR_FAIL_S,	/*!< Generic driver failure */
	OS_ERROR_NO_MEMORY_S,	/*!< Failure to acquire/use memory  */
	OS_ERROR_BAD_ADDRESS_S,	/*!< Bad address  */
	OS_ERROR_BAD_ARG_S	/*!< Bad input argument */
} os_error_code;

/*!
 * Handle to a lock.
 */
typedef int *os_lock_t;

/*!
 * Context while locking.
 */
typedef int os_lock_context_t;

/*!
 * An object which can be slept on and later used to wake any/all sleepers.
 */
typedef int os_sleep_object_t;

/*!
 * Driver registration handle
 */
typedef void *os_driver_reg_t;

/*!
 * Function signature for an #OS_DEV_INIT() function.
 *
 * @return  A call to os_dev_init_return() function.
 */
typedef void (*os_init_function_t) (void);

/*!
 * Function signature for an #OS_DEV_SHUTDOWN() function.
 *
 * @return  A call to os_dev_shutdown_return() function.
 */
typedef void (*os_shutdown_function_t) (void);

/*!
 * Function signature for a user-driver function.
 *
 * @return  A call to the appropriate os_dev_xxx_return() function.
 */
typedef void (*os_user_function_t) (void);

/*!
 * Function signature for the portable interrupt handler
 *
 * While it would be nice to know which interrupt is being serviced, the
 * Least Common Denominator rule says that no arguments get passed in.
 *
 * @return  A call to #os_dev_isr_return()
 */
typedef void (*os_interrupt_handler_t) (void);

/*!
 * Function signature for a task function
 *
 * Many task function definitions get some sort of generic argument so that the
 * same function can run across many (queues, channels, ...) as separate task
 * instances.  This has been left out of this API.
 *
 * This function must be structured as documented by #OS_DEV_TASK().
 *
 */
typedef void (*os_task_fn_t) (void);

/*!
 *  Function types which can be associated with driver entry points.  These are
 *  used in os_driver_add_registration().
 *
 *  Note that init and shutdown are absent.
 */
typedef enum {
	OS_FN_OPEN,		/*!< open() operation handler. */
	OS_FN_CLOSE,		/*!< close() operation handler. */
	OS_FN_READ,		/*!< read() operation handler. */
	OS_FN_WRITE,		/*!< write() operation handler. */
	OS_FN_IOCTL,		/*!< ioctl() operation handler. */
	OS_FN_MMAP		/*!< mmap() operation handler. */
} os_driver_fn_t;

/***************************************************************************
 * Driver-to-Kernel Operations
 **************************************************************************/

/*!
 * @defgroup dkops Driver-to-Kernel Operations
 *
 * These are the operations which drivers should call to get the OS to perform
 * services.
 */

/*! @addtogroup dkops */
/*! @{ */

/*!
 * Register an interrupt handler.
 *
 * @param driver_name    The name of the driver
 * @param interrupt_id   The interrupt line to monitor (type
 *                       #os_interrupt_id_t)
 * @param function       The function to be called to handle an interrupt
 *
 * @return #os_error_code
 */
os_error_code os_register_interrupt(char *driver_name,
				    os_interrupt_id_t interrupt_id,
				    os_interrupt_handler_t function);

/*!
 * Deregister an interrupt handler.
 *
 * @param interrupt_id   The interrupt line to stop monitoring
 *
 * @return #os_error_code
 */
os_error_code os_deregister_interrupt(os_interrupt_id_t interrupt_id);

/*!
 * Initialize driver registration.
 *
 * If the driver handles open(), close(), ioctl(), read(), write(), or mmap()
 * calls, then it needs to register their location with the kernel so that they
 * get associated with the device.
 *
 * @param handle  The handle object to be used with this registration.  The
 *                object must live (be in memory somewhere) at least until
 *                os_driver_remove_registration() is called.
 *
 * @return An os error code.
 */
os_error_code os_driver_init_registration(os_driver_reg_t handle);

/*!
 * Add a function registration to driver registration.
 *
 * @param handle    The handle used with #os_driver_init_registration().
 * @param name      Which function is being supported.
 * @param function  The result of a call to a @c _REF version of one of the
 *                  driver function signature macros
 *                  driver function signature macros
 * @return void
 */
void os_driver_add_registration(os_driver_reg_t handle, os_driver_fn_t name,
				void *function);

/*!
 * Finalize the driver registration with the kernel.
 *
 * Upon return from this call, the driver may begin receiving calls at the
 * defined entry points.
 *
 * @param handle    The handle used with #os_driver_init_registration().
 * @param major      The major device number to be associated with the driver.
 *                   If this value is zero, a major number may be assigned.
 *                   See #os_driver_get_major() to determine final value.
 *                   #os_driver_remove_registration().
 * @param driver_name The driver name.  Can be used as part of 'device node'
 *                   name on platforms which support such a feature.
 *
 * @return  An error code
 */
os_error_code os_driver_complete_registration(os_driver_reg_t handle,
					      int major, char *driver_name);

/*!
 * Get driver Major Number from handle after a successful registration.
 *
 * @param   handle  A handle which has completed registration.
 *
 * @return The major number (if any) associated with the handle.
 */
uint32_t os_driver_get_major(os_driver_reg_t handle);

/*!
 * Remove the driver's registration with the kernel.
 *
 * Upon return from this call, the driver not receive any more calls at the
 * defined entry points (other than ISR and shutdown).
 *
 * @param major       The major device number to be associated with the driver.
 * @param driver_name The driver name
 *
 * @return  An error code.
 */
os_error_code os_driver_remove_registration(int major, char *driver_name);

/*!
 * Print a message to console / into log file.  After the @c msg argument a
 * number of printf-style arguments may be added.  Types should be limited to
 * printf string, char, octal, decimal, and hexadecimal types.  (This excludes
 * pointers, and floating point).
 *
 * @param  msg  The message to print to console / system log
 *
 * @return (void)
 */
void os_printk(char *msg, ...);

/*!
 * Allocate some kernel memory
 *
 * @param amount   Number of 8-bit bytes to allocate
 * @param flags    Some indication of purpose of memory (needs definition)
 *
 * @return  Pointer to allocated memory, or NULL if failed.
 */
void *os_alloc_memory(unsigned amount, int flags);

/*!
 * Free some kernel memory
 *
 * @param location  The beginning of the region to be freed.
 *
 * Do some OSes have separate free() functions which should be
 * distinguished by passing in @c flags here, too? Don't some also require the
 * size of the buffer being freed?  Perhaps separate routines for each
 * alloc/free pair (DMAable, etc.)?
 */
void os_free_memory(void *location);

/*!
 * Allocate cache-coherent memory
 *
 * @param       amount     Number of bytes to allocate
 * @param[out]  dma_addrp  Location to store physical address of allocated
 *                         memory.
 * @param       flags      Some indication of purpose of memory (needs
 *                         definition).
 *
 * @return (virtual space) pointer to allocated memory, or NULL if failed.
 *
 */
void *os_alloc_coherent(unsigned amount, uint32_t * dma_addrp, int flags);

/*!
 * Free cache-coherent memory
 *
 * @param       size       Number of bytes which were allocated.
 * @param[out]  virt_addr  Virtual(kernel) address of memory.to be freed, as
 *                         returned by #os_alloc_coherent().
 * @param[out]  dma_addr   Physical address of memory.to be freed, as returned
 *                         by #os_alloc_coherent().
 *
 * @return void
 *
 */
void os_free_coherent(unsigned size, void *virt_addr, uint32_t dma_addr);

/*!
 * Map an I/O space into kernel memory space
 *
 * @param start       The starting address of the (physical / io space) region
 * @param range_bytes The number of bytes to map
 *
 * @return A pointer to the mapped area, or NULL on failure
 */
void *os_map_device(uint32_t start, unsigned range_bytes);

/*!
 * Unmap an I/O space from kernel memory space
 *
 * @param start       The starting address of the (virtual) region
 * @param range_bytes The number of bytes to unmap
 *
 * @return None
 */
void os_unmap_device(void *start, unsigned range_bytes);

/*!
 * Copy data from Kernel space to User space
 *
 * @param to   The target location in user memory
 * @param from The source location in kernel memory
 * @param size The number of bytes to be copied
 *
 * @return #os_error_code
 */
os_error_code os_copy_to_user(void *to, void *from, unsigned size);

/*!
 * Copy data from User space to Kernel space
 *
 * @param to   The target location in kernel memory
 * @param from The source location in user memory
 * @param size The number of bytes to be copied
 *
 * @return #os_error_code
 */
os_error_code os_copy_from_user(void *to, void *from, unsigned size);

/*!
 * Read an 8-bit device register
 *
 * @param register_address  The (bus) address of the register to write to
 * @return                  The value in the register
 */
uint8_t os_read8(uint8_t * register_address);

/*!
 * Write an 8-bit device register
 *
 * @param register_address  The (bus) address of the register to write to
 * @param value             The value to write into the register
 */
void os_write8(uint8_t * register_address, uint8_t value);

/*!
 * Read a 16-bit device register
 *
 * @param register_address  The (bus) address of the register to write to
 * @return                  The value in the register
 */
uint16_t os_read16(uint16_t * register_address);

/*!
 * Write a 16-bit device register
 *
 * @param register_address  The (bus) address of the register to write to
 * @param value             The value to write into the register
 */
void os_write16(uint16_t * register_address, uint16_t value);

/*!
 * Read a 32-bit device register
 *
 * @param register_address  The (bus) address of the register to write to
 * @return                  The value in the register
 */
uint32_t os_read32(uint32_t * register_address);

/*!
 * Write a 32-bit device register
 *
 * @param register_address  The (bus) address of the register to write to
 * @param value             The value to write into the register
 */
void os_write32(uint32_t * register_address, uint32_t value);

/*!
 * Read a 64-bit device register
 *
 * @param register_address  The (bus) address of the register to write to
 * @return                  The value in the register
 */
uint64_t os_read64(uint64_t * register_address);

/*!
 * Write a 64-bit device register
 *
 * @param register_address  The (bus) address of the register to write to
 * @param value             The value to write into the register
 */
void os_write64(uint64_t * register_address, uint64_t value);

/*!
 * Prepare a task to execute the given function.  This should only be done once
 * per task, during the driver's initialization routine.
 *
 * @param task_fn   Name of the OS_DEV_TASK() function to be created.
 *
 * @return an OS ERROR code.
 */
os_error os_create_task(os_task_fn_t * task_fn);

/*!
 * Run the task associated with an #OS_DEV_TASK() function
 *
 * The task will begin execution sometime after or during this call.
 *
 * @param task_fn   Name of the OS_DEV_TASK() function to be scheduled.
 *
 * @return void
 */
void os_dev_schedule_task(os_task_fn_t * task_fn);

/*!
 * Make sure that task is no longer running and will no longer run.
 *
 * This function will not return until both are true.  This is useful when
 * shutting down a driver.
 *
 * @param task_fn   Name of the OS_DEV_TASK() funciton to be stopped.
 *
 */
void os_stop_task(os_task_fn_t * task_fn);

/*!
 * Delay some number of microseconds
 *
 * Note that this is a busy-loop, not a suspension of the task/process.
 *
 * @param  msecs   The number of microseconds to delay
 *
 * @return void
 */
void os_mdelay(unsigned long msecs);

/*!
 * Calculate virtual address from physical address
 *
 * @param pa    Physical address
 *
 * @return virtual address
 *
 * @note this assumes that addresses are 32 bits wide
 */
void *os_va(uint32_t pa);

/*!
 * Calculate physical address from virtual address
 *
 *
 * @param va    Virtual address
 *
 * @return physical address
 *
 * @note this assumes that addresses are 32 bits wide
 */
uint32_t os_pa(void *va);

/*!
 * Allocate and initialize a lock, returning a lock handle.
 *
 * The lock state will be initialized to 'unlocked'.
 *
 * @return A lock handle, or NULL if an error occurred.
 */
os_lock_t os_lock_alloc_init(void);

/*!
 * Acquire a lock.
 *
 * This function should only be called from an interrupt service routine.
 *
 * @param   lock_handle  A handle to the lock to acquire.
 *
 * @return void
 */
void os_lock(os_lock_t lock_handle);

/*!
 * Unlock a lock.  Lock must have been acquired by #os_lock().
 *
 * @param   lock_handle  A handle to the lock to unlock.
 *
 * @return void
 */
void os_unlock(os_lock_t lock_handle);

/*!
 * Acquire a lock in non-ISR context
 *
 * This function will spin until the lock is available.
 *
 * @param lock_handle  A handle of the lock to acquire.
 * @param context      Place to save the before-lock context
 *
 * @return void
 */
void os_lock_save_context(os_lock_t lock_handle, os_lock_context_t context);

/*!
 * Release a lock in non-ISR context
 *
 * @param lock_handle  A handle of the lock to release.
 * @param context      Place where before-lock context was saved.
 *
 * @return void
 */
void os_unlock_restore_context(os_lock_t lock_handle,
			       os_lock_context_t context);

/*!
 * Deallocate a lock handle.
 *
 * @param lock_handle   An #os_lock_t that has been allocated.
 *
 * @return void
 */
void os_lock_deallocate(os_lock_t lock_handle);

/*!
 * Determine process handle
 *
 * The process handle of the current user is returned.
 *
 * @return   A handle on the current process.
 */
os_process_handle_t os_get_process_handle();

/*!
 * Send a signal to a process
 *
 * @param  proc   A handle to the target process.
 * @param  sig    The POSIX signal to send to that process.
 */
void os_send_signal(os_process_handle_t proc, int sig);

/*!
 * Get some random bytes
 *
 * @param buf    The location to store the random data.
 * @param count  The number of bytes to store.
 *
 * @return  void
 */
void os_get_random_bytes(void *buf, unsigned count);

/*!
 * Go to sleep on an object.
 *
 * Example: code = os_sleep(my_queue, available_count == 0, 0);
 *
 * @param object    The object on which to sleep
 * @param condition An expression to check for sleep completion.  Must be
 *                  coded so that it can be referenced more than once inside
 *                  macro, i.e., no ++ or other modifying expressions.
 * @param atomic    Non-zero if sleep must not return until condition.
 *
 * @return error code -- OK or sleep interrupted??
 */
os_error_code os_sleep(os_sleep_object_t object, unsigned condition,
		       unsigned atomic);

/*!
 * Wake up whatever is sleeping on sleep object
 *
 * @param object  The object on which things might be sleeping
 *
 * @return none
 */
void os_wake_sleepers(os_sleep_object_t object);

	  /*! @} *//* dkops */

/*****************************************************************************
 *  Function-signature-generating macros
 *****************************************************************************/

/*!
 * @defgroup drsigs Driver Function Signatures
 *
 * These macros will define the entry point signatures for interrupt handlers;
 * driver initialization and shutdown; device open/close; etc.  They are to be
 * used whenever the Kernel will call into the Driver.  They are not
 * appropriate for driver calls to other routines in the driver.
 *
 * There are three versions of each macro for a given Driver Entry Point.  The
 * first version is used to define a function and its implementation in the
 * driver.c file, e.g. #OS_DEV_INIT().
 *
 * The second form is used whenever a forward declaration (prototype) is
 * needed.  It has the letters @c _DCL appended to the name of the definition
 * function.  These are not otherwise mentioned in this documenation.
 *
 * There is a third form used when a reference to a function is required, for
 * instance when passing the routine as a pointer to a function.  It has the
 * letters @c _REF appended to the name of the definition function
 * (e.g. DEV_IOCTL_REF).
 *
 * Note that these two extra forms are required because of the possibility of
 * having an invisible 'wrapper function' created by the os-specific header
 * file which would need to be invoked by the operating system, and which in
 * turn would invoke the generic function.
 *
 * Example:
 *
 * (in a header file)
 * @code
 * OS_DEV_INIT_DCL(widget_init);
 * OS_DEV_ISR_DCL(widget_isr);
 * @endcode
 *
 * (in an implementation file)
 * @code
 * OS_DEV_INIT(widget, widget_init)
 * {
 *
 *     os_register_interrupt("widget", WIDGET_IRQ, OS_DEV_ISR_REF(widget_isr));
 *
 *     os_dev_init_return(OS_RETURN_NO_ERROR_S);
 * }
 *
 * OS_DEV_ISR(widget_isr)
 * {
 *     os_dev_isr_return(TRUE);
 * }
 * @endcode
 */

/*! @addtogroup drsigs */
/*! @{ */

/*!
 * Define a function which will handle device initialization
 *
 * This is tne driver initialization routine.  This is normally where the
 * part would be initialized; queues, locks, interrupts handlers defined;
 * long-term dynamic memory allocated for driver use; etc.
 *
 * @param function_name   The name of the portable initialization function.
 *
 * @return  A call to #os_dev_init_return()
 *
 */
#define OS_DEV_INIT(function_name)

/*!
 * Define a function which will handle device shutdown
 *
 * This is the reverse of the #OS_DEV_INIT() routine.
 *
 * @param function_name   The name of the portable driver shutdown routine.
 *
 * @return  A call to #os_dev_shutdown_return()
 */
#define OS_DEV_SHUTDOWN(function_name)

/*!
 * Define a function which will open the device for a user.
 *
 * @param function_name The name of the driver open() function
 *
 * @return A call to #os_dev_open_return()
 */
#define OS_DEV_OPEN(function_name)

/*!
 * Define a function which will handle a user's ioctl() request
 *
 * @param function_name The name of the driver ioctl() function
 *
 * @return A call to #os_dev_ioctl_return()
 */
#define OS_DEV_IOCTL(function_name)

/*!
 * Define a function which will handle a user's read() request
 *
 * @param function_name The name of the driver read() function
 *
 * @return A call to #os_dev_read_return()
 */
#define OS_DEV_READ(function_name)

/*!
 * Define a function which will handle a user's write() request
 *
 * @param function_name The name of the driver write() function
 *
 * @return A call to #os_dev_write_return()
 */
#define OS_DEV_WRITE(function_name)

/*!
 * Define a function which will handle a user's mmap() request
 *
 * The mmap() function requests the driver to map some memory into user space.
 *
 * @todo Determine what support functions are needed for mmap() handling.
 *
 * @param function_name The name of the driver mmap() function
 *
 * @return A call to #os_dev_mmap_return()
 */
#define OS_DEV_MMAP(function_name)

/*!
 * Define a function which will close the device - opposite of OS_DEV_OPEN()
 *
 * @param function_name The name of the driver close() function
 *
 * @return A call to #os_dev_close_return()
 */
#define OS_DEV_CLOSE(function_name)

/*!
 * Define a function which will handle an interrupt
 *
 * No arguments are available to the generic function.  It must not invoke any
 * OS functions which are illegal in a ISR.  It gets no parameters, and must
 * have a call to #os_dev_isr_return() instead of any/all return statements.
 *
 * Example:
 * @code
 * OS_DEV_ISR(widget, widget_isr, WIDGET_IRQ_NUMBER)
 * {
 *     os_dev_isr_return(1);
 * }
 * @endcode
 *
 * @param function_name The name of the driver ISR function
 *
 * @return   A call to #os_dev_isr_return()
 */
#define OS_DEV_ISR(function_name)

/*!
 * Define a function which will operate as a background task / bottom half.
 *
 * The function implementation must be structured in the following manner:
 * @code
 * OS_DEV_TASK(widget_task)
 * {
 *     OS_DEV_TASK_SETUP(widget_task);
 *
 *     while OS_DEV_TASK_CONDITION(widget_task) }
 *
 *     };
 * }
 * @endcode
 *
 * @todo In some systems the OS_DEV_TASK_CONDITION() will be an action which
 * will cause the task to sleep on some event triggered by os_run_task().  In
 * others, the macro will reference a variable laid down by
 * OS_DEV_TASK_SETUP() to make sure that the loop is only performed once.
 *
 * @param function_name The name of this background task function
 */
#define OS_DEV_TASK(function_name)

	  /*! @} *//* drsigs */

/*! @defgroup dclsigs Routines to declare Driver Signature routines
 *
 * These macros drop prototypes suitable for forward-declaration of
 * @ref drsigs "function signatures".
 */

/*! @addtogroup dclsigs */
/*! @{ */

/*!
 * Declare prototype for the device initialization function
 *
 * @param function_name   The name of the portable initialization function.
 */
#define OS_DEV_INIT_DCL(function_name)

/*!
 * Declare prototype for the device shutdown function
 *
 * @param function_name   The name of the portable driver shutdown routine.
 *
 * @return  A call to #os_dev_shutdown_return()
 */
#define OS_DEV_SHUTDOWN_DCL(function_name)

/*!
 * Declare prototype for the open() function.
 *
 * @param function_name The name of the driver open() function
 *
 * @return A call to #os_dev_open_return()
 */
#define OS_DEV_OPEN_DCL(function_name)

/*!
 * Declare prototype for the user's ioctl() request function
 *
 * @param function_name The name of the driver ioctl() function
 *
 * @return A call to #os_dev_ioctl_return()
 */
#define OS_DEV_IOCTL_DCL(function_name)

/*!
 * Declare prototype for the function a user's read() request
 *
 * @param function_name The name of the driver read() function
 */
#define OS_DEV_READ_DCL(function_name)

/*!
 * Declare prototype for the user's write() request function
 *
 * @param function_name The name of the driver write() function
 */
#define OS_DEV_WRITE_DCL(function_name)

/*!
 * Declare prototype for the user's mmap() request function
 *
 * @param function_name The name of the driver mmap() function
 */
#define OS_DEV_MMAP_DCL(function_name)

/*!
 * Declare prototype for the close function
 *
 * @param function_name The name of the driver close() function
 *
 * @return A call to #os_dev_close_return()
 */
#define OS_DEV_CLOSE_DCL(function_name)

/*!
 * Declare prototype for the interrupt handling function
 *
 * @param function_name The name of the driver ISR function
 */
#define OS_DEV_ISR_DCL(function_name)

/*!
 * Declare prototype for a background task / bottom half function
 *
 * @param function_name The name of this background task function
 */
#define OS_DEV_TASK_DCL(function_name)

	  /*! @} *//* dclsigs */

/*****************************************************************************
 *  Functions for Returning Values from Driver Signature routines
 *****************************************************************************/

/*!
 * @defgroup retfns Functions to Return Values from Driver Signature routines
 */

/*! @addtogroup retfns */
/*! @{ */

/*!
 * Return from the #OS_DEV_INIT() function
 *
 * @param code    An error code to report success or failure.
 *
 */
void os_dev_init_return(os_error_code code);

/*!
 * Return from the #OS_DEV_SHUTDOWN() function
 *
 * @param code    An error code to report success or failure.
 *
 */
void os_dev_shutdown_return(os_error_code code);

/*!
 * Return from the #OS_DEV_ISR() function
 *
 * The function should verify that it really was supposed to be called,
 * and that its device needed attention, in order to properly set the
 * return code.
 *
 * @param code    non-zero if interrupt handled, zero otherwise.
 *
 */
void os_dev_isr_return(int code);

/*!
 * Return from the #OS_DEV_OPEN() function
 *
 * @param code    An error code to report success or failure.
 *
 */
void os_dev_open_return(os_error_code code);

/*!
 * Return from the #OS_DEV_IOCTL() function
 *
 * @param code    An error code to report success or failure.
 *
 */
void os_dev_ioctl_return(os_error_code code);

/*!
 * Return from the #OS_DEV_READ() function
 *
 * @param code    Number of bytes read, or an error code to report failure.
 *
 */
void os_dev_read_return(os_error_code code);

/*!
 * Return from the #OS_DEV_WRITE() function
 *
 * @param code    Number of bytes written, or an error code to report failure.
 *
 */
void os_dev_write_return(os_error_code code);

/*!
 * Return from the #OS_DEV_MMAP() function
 *
 * @param code    Number of bytes written, or an error code to report failure.
 *
 */
void os_dev_mmap_return(os_error_code code);

/*!
 * Return from the #OS_DEV_CLOSE() function
 *
 * @param code    An error code to report success or failure.
 *
 */
void os_dev_close_return(os_error_code code);

/*!
 * Start the #OS_DEV_TASK() function
 *
 * In some implementations, this could be turned into a label for
 * the os_dev_task_return() call.
 *
 * For a more portable interface, should this take the sleep object as an
 * argument???
 *
 * @return none
 */
void os_dev_task_begin(void);

/*!
 * Return from the #OS_DEV_TASK() function
 *
 * In some implementations, this could be turned into a sleep followed
 * by a jump back to the os_dev_task_begin() call.
 *
 * @param code    An error code to report success or failure.
 *
 */
void os_dev_task_return(os_error_code code);

	  /*! @} *//* retfns */

/*****************************************************************************
 *  Functions/Macros for accessing arguments from Driver Signature routines
 *****************************************************************************/

/*! @defgroup drsigargs Functions for Getting Arguments in Signature functions
 *
 */
/* @addtogroup @drsigargs */
/*! @{ */

/*!
 * Check whether user is requesting read (permission) on the file/device.
 * Usable in #OS_DEV_OPEN(), #OS_DEV_CLOSE(), #OS_DEV_IOCTL(), #OS_DEV_READ()
 * and #OS_DEV_WRITE() routines.
 */
int os_dev_is_flag_read(void);

/*!
 * Check whether user is requesting write (permission) on the file/device.
 * Usable in #OS_DEV_OPEN(), #OS_DEV_CLOSE(), #OS_DEV_IOCTL(), #OS_DEV_READ()
 * and #OS_DEV_WRITE() routines.
 */
int os_dev_is_flag_write(void);

/*!
 * Check whether user is requesting non-blocking I/O.  Usable in
 * #OS_DEV_OPEN(), #OS_DEV_CLOSE(), #OS_DEV_IOCTL(), #OS_DEV_READ() and
 * #OS_DEV_WRITE() routines.
 *
 * @todo Specify required behavior when nonblock is requested and (sufficient?)
 * data are not available to fulfill the request.
 *
 */
int os_dev_is_flag_nonblock(void);

/*!
 * Determine which major device is being accessed.  Usable in #OS_DEV_OPEN()
 * and #OS_DEV_CLOSE().
 */
int os_dev_get_major(void);

/*!
 * Determine which minor device is being accessed.  Usable in #OS_DEV_OPEN()
 * and #OS_DEV_CLOSE().
 */
int os_dev_get_minor(void);

/*!
 * Determine which operation the user wants performed.  Usable in
 * #OS_DEV_IOCTL().
 *
 * @return  Value of the operation.
 *
 * @todo Define some generic way to define the individual operations.
 */
unsigned os_dev_get_ioctl_op(void);

/*!
 * Retrieve the associated argument for the desired operation.  Usable in
 * #OS_DEV_IOCTL().
 *
 * @return    A value which can be cast to a struct pointer or used as
 *            int/long.
 */
os_dev_ioctl_arg_t os_dev_get_ioctl_arg(void);

/*!
 * Determine the requested byte count. This should be the size of buffer at
 * #os_dev_get_user_buffer(). Usable in OS_DEV_READ() and OS_DEV_WRITE()
 * routines.
 *
 * @return   A count of bytes
 */
unsigned os_dev_get_count(void);

/*!
 * Get the pointer to the user's data buffer. Usable in OS_DEV_READ(),
 * OS_DEV_WRITE(), and OS_DEV_MMAP() routines.
 *
 * @return   Pointer to user buffer (in user space).  See #os_copy_to_user()
 *           and #os_copy_from_user().
 */
void *os_dev_get_user_buffer(void);

/*!
 * Get the POSIX flags field for the associated open file.  Usable in
 * OS_DEV_READ(), OS_DEV_WRITE(), and OS_DEV_IOCTL() routines.
 *
 * @return The flags associated with the file.
 */
unsigned os_dev_get_file_flags(void);

/*!
 * Set the driver's private structure associated with this file/open.
 *
 * Generally used during #OS_DEV_OPEN().  May also be used during
 * #OS_DEV_READ(), #OS_DEV_WRITE(), #OS_DEV_IOCTL(), #OS_DEV_MMAP(), and
 * #OS_DEV_CLOSE().  See also #os_dev_get_user_private().
 *
 * @param  struct_p   The driver data structure to associate with this user.
 */
void os_dev_set_user_private(void *struct_p);

/*!
 * Get the driver's private structure associated with this file.
 *
 * May be used during #OS_DEV_OPEN(), #OS_DEV_READ(), #OS_DEV_WRITE(),
 * #OS_DEV_IOCTL(), #OS_DEV_MMAP(), and #OS_DEV_CLOSE().  See
 * also #os_dev_set_user_private().
 *
 * @return   The driver data structure to associate with this user.
 */
void *os_dev_get_user_private(void);

/*!
 * Get the IRQ associated with this call to the #OS_DEV_ISR() function.
 *
 * @return  The IRQ (integer) interrupt number.
 */
int os_dev_get_irq(void);

	  /*! @} *//* drsigargs */

/*****************************************************************************
 *  Functions for Generating References to Driver Routines
 *****************************************************************************/

/*!
 * @defgroup drref Functions for Generating References to Driver Routines
 *
 * These functions will most likely be implemented as macros.  They are a
 * necessary part of the portable API to guarantee portability.  The @c symbol
 * type in here is the same symbol passed to the associated
 * signature-generating macro.
 *
 * These macros must be used whenever referring to a
 * @ref drsigs "driver signature function", for instance when storing or
 * passing a pointer to the function.
 */

/*! @addtogroup drref */
/*! @{ */

/*!
 * Generate a reference to an #OS_DEV_INIT() function
 *
 * @param function_name   The name of the init function being referenced.
 *
 * @return A reference to the function
 */
os_init_function_t OS_DEV_INIT_REF(symbol function_name);

/*!
 * Generate a reference to an #OS_DEV_SHUTDOWN() function
 *
 * @param function_name   The name of the shutdown function being referenced.
 *
 * @return A reference to the function
 */
os_shutdown_function_t OS_DEV_SHUTDOWN_REF(symbol function_name);

/*!
 * Generate a reference to an #OS_DEV_OPEN() function
 *
 * @param function_name   The name of the open function being referenced.
 *
 * @return A reference to the function
 */
os_user_function_t OS_DEV_OPEN_REF(symbol function_name);

/*!
 * Generate a reference to an #OS_DEV_CLOSE() function
 *
 * @param function_name   The name of the close function being referenced.
 *
 * @return A reference to the function
 */
os_user_function_t OS_DEV_CLOSE_REF(symbol function_name);

/*!
 * Generate a reference to an #OS_DEV_READ() function
 *
 * @param function_name   The name of the read function being referenced.
 *
 * @return A reference to the function
 */
os_user_function_t OS_DEV_READ_REF(symbol function_name);

/*!
 * Generate a reference to an #OS_DEV_WRITE() function
 *
 * @param function_name   The name of the write function being referenced.
 *
 * @return A reference to the function
 */
os_user_function_t OS_DEV_WRITE_REF(symbol function_name);

/*!
 * Generate a reference to an #OS_DEV_IOCTL() function
 *
 * @param function_name   The name of the ioctl function being referenced.
 *
 * @return A reference to the function
 */
os_user_function_t OS_DEV_IOCTL_REF(symbol function_name);

/*!
 * Generate a reference to an #OS_DEV_MMAP() function
 *
 * @param function_name   The name of the mmap function being referenced.
 *
 * @return A reference to the function
 */
os_user_function_t OS_DEV_MMAP_REF(symbol function_name);

/*!
 * Generate a reference to an #OS_DEV_ISR() function
 *
 * @param function_name   The name of the isr being referenced.
 *
 * @return a reference to the function
 */
os_interrupt_handler_t OS_DEV_ISR_REF(symbol function_name);

	  /*! @} *//* drref */

/*!
 * Flush and invalidate all cache lines.
 */
void os_flush_cache_all(void);

/*!
 * Flush a range of addresses from the cache
 *
 * @param  start    Starting virtual address
 * @param  len      Number of bytes to flush
 */
void os_cache_flush_range(void *start, uint32_t len);

/*!
 * Invalidate a range of addresses in the cache
 *
 * @param  start    Starting virtual address
 * @param  len      Number of bytes to flush
 */
void os_cache_inv_range(void *start, uint32_t len);

/*!
 * Clean a range of addresses from the cache
 *
 * @param  start    Starting virtual address
 * @param  len      Number of bytes to flush
 */
void os_cache_clean_range(void *start, uint32_t len);

/*!
  * @example widget.h
  */

/*!
  * @example widget.c
  */

/*!
  * @example rng_driver.h
  */

/*!
  * @example rng_driver.c
  */

/*!
  * @example shw_driver.h
  */

/*!
  * @example shw_driver.c
  */

#endif				/* DOXYGEN_PORTABLE_OS_DOC */

#endif				/* PORTABLE_OS_H */