Annotation of prex-old/doc/html/doc/dki.html, Revision 1.1.1.1
1.1 nbrk 1: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2: <html>
3: <head>
4: <title>Prex Driver-Kernel Interface</title>
5: <meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
6: <meta name="keywords" content="Prex, embedded, real-time, operating system, RTOS, open source, free">
7: <meta name="author" content="Kohsuke Ohtani">
8: <link rel="stylesheet" type="text/css" href="../default.css" media="screen">
9: <link rel="stylesheet" type="text/css" href="../print.css" media="print">
10: </head>
11: <body>
12: <div id="top">
13: </div>
14: <div id="middle">
15:
16: <table id="content" cellpadding="0" cellspacing="0">
17: <tbody>
18:
19: <tr>
20: <td id="header" colspan="2" valign="top">
21: <table width="100%" border="0" cellspacing="0" cellpadding="0">
22: <tr>
23: <td id="logo">
24: <a href="http://prex.sourceforge.net/">
25: <img alt="Prex logo" src="../img/logo.gif" border="0"
26: style="width: 281px; height: 56px;"></a>
27: </td>
28: <td id="brief" align="right" valign="bottom">
29: An Open Source, Royalty-free,<br>
30: Real-time Operating System
31: </td>
32: </tr>
33: </table>
34: </td>
35: </tr>
36:
37: <tr>
38: <td id="directory" style="vertical-align: top;">
39: <a href="http://prex.sourceforge.net/">Prex Home</a> >
40: <a href="index.html">Document Index</a> >
41: Driver-Kernel Interface
42: </tr>
43: <tr><td class="pad" colspan="2" style="vertical-align: top;"></td></tr>
44:
45: <tr>
46: <td id="main" style="vertical-align: top;">
47: <h1>Prex Driver-Kernel Interface</h1>
48:
49: <i>Version 1.0.2, 2007/12/23</i><br>
50: <br>
51:
52: <h3>Table of Contents</h3>
53: <ul>
54: <li><a href="#intro">Introduction</a></li>
55: </ul>
56: <ul>
57: <li><a href="#gen">General Information</a>
58: <ul>
59: <li><a href="#gen">Data Types</a></li>
60: <li><a href="#gen">Calls from ISR</a></li>
61: </ul>
62: </li>
63: </ul>
64: <ul>
65: <li><a href="#obj">Device Object</a>
66: <ul>
67: <li><a href="#obj">device_create</a></li>
68: <li><a href="#obj">device_delete</a></li>
69: <li><a href="#obj">device_broadcast</a></li>
70: </ul>
71: </li>
72: </ul>
73: <ul>
74: <li><a href="#kmem">Kernel Memory</a>
75: <ul>
76: <li><a href="#kmem">kmem_alloc</a></li>
77: <li><a href="#kmem">kmem_free</a></li>
78: <li><a href="#kmem">kmem_map</a></li>
79: </ul>
80: </li>
81: </ul>
82: <ul>
83: <li><a href="#umem">User Memory</a>
84: <ul>
85: <li><a href="#umem">umem_copyin</a></li>
86: <li><a href="#umem">umem_copyout</a></li>
87: <li><a href="#umem">umem_strnlen</a></li>
88: </ul>
89: </li>
90: </ul>
91: <ul>
92: <li><a href="#page">Physical Page</a>
93: <ul>
94: <li><a href="#page">page_alloc</a></li>
95: <li><a href="#page">page_free</a></li>
96: <li><a href="#page">page_reserve</a></li>
97: </ul>
98: </li>
99: </ul>
100: <ul>
101: <li><a href="#int">Interrupt</a>
102: <ul>
103: <li><a href="#int">irq_attach</a></li>
104: <li><a href="#int">irq_detach</a></li>
105: <li><a href="#int">irq_lock</a></li>
106: <li><a href="#int">irq_unlock</a></li>
107: </ul>
108: </li>
109: </ul>
110: <ul>
111: <li><a href="#sched">Scheduler</a>
112: <ul>
113: <li><a href="#sched">sched_lock</a></li>
114: <li><a href="#sched">sched_unlock</a></li>
115: <li><a href="#sched">sched_tsleep</a></li>
116: <li><a href="#sched">sched_wakeup</a></li>
117: <li><a href="#sched">sched_dpc</a></li>
118: </ul>
119: </li>
120: </ul>
121: <ul>
122: <li><a href="#timer">Timer</a>
123: <ul>
124: <li><a href="#timer">timer_callout</a></li>
125: <li><a href="#timer">timer_stop</a></li>
126: <li><a href="#timer">timer_delay</a></li>
127: <li><a href="#timer">timer_count</a></li>
128: <li><a href="#timer">timer_hook</a></li>
129: </ul>
130: </li>
131: </ul>
132: <ul>
133: <li><a href="#misc">Miscellaneous</a>
134: <ul>
135: <li><a href="#misc">task_capable</a></li>
136: <li><a href="#misc">exception_post</a></li>
137: <li><a href="#misc">phys_to_virt</a></li>
138: <li><a href="#misc">virt_to_phys</a></li>
139: <li><a href="#misc">machine_reset</a></li>
140: <li><a href="#misc">machine_dump</a></li>
141: <li><a href="#misc">debug_attach</a></li>
142: <li><a href="#misc">printk</a></li>
143: <li><a href="#misc">panic</a></li>
144: </ul>
145: </li>
146: </ul>
147: <br>
148: <br>
149:
150: <h2 id="intro">Introduction</h2>
151: <p>
152: The Prex kernel provides the minimum service for the device drivers.
153: Since the driver module is separated from the kernel module, the drivers
154: can not access other kernel functions beyond this interface.
155: This mechanism helps to isolate the kernel from the driver codes.
156: </p>
157: <p>
158: This document describes the Driver-Kernel Interface (DKI) that can be
159: used by device drivers.
160: </p>
161:
162: <h2 id="gen">General Information</h2>
163:
164: <h3>Data Types</h3>
165: <p>
166: The following data types are defined by kernel.
167: </p>
168:
169: <table border="1" width="60%" cellspacing="0">
170: <tbody>
171: <tr>
172: <th>Data type</th>
173: <th>Description</th>
174: </tr>
175:
176: <tr>
177: <td>device_t</td>
178: <td>Used to identify the device object.</td>
179: </tr>
180: <tr>
181: <td>task_t</td>
182: <td>Used to identify the task.</td>
183: </tr>
184: </tbody>
185: </table>
186:
187: <h3>Calls from ISR</h3>
188: <p>
189: The driver-kernel service is limited at interrupt level
190: because the kernel does not synchronize all data accesses
191: for interrupt level access.
192: So, the device driver can use only the following functions
193: from the interrupt service routine.
194: </p>
195: <ul>
196: <li>irq_lock()</li>
197: <li>irq_unlock()</li>
198: <li>sched_wakeup()</li>
199: <li>sched_stat()</li>
200: <li>timer_callout()</li>
201: <li>timer_stop()</li>
202: <li>timer_count()</li>
203: <li>sched_lock()</li>
204: <li>sched_unlock()</li>
205: <li>sched_tsleep()</li>
206: <li>sched_wakeup()</li>
207: <li>sched_dpc()</li>
208: <li>exception_post()</li>
209: <li>printk()</li>
210: <li>panic()</li>
211: <li>machine_reset()</li>
212: <li>machine_dump()</li>
213: </ul>
214:
215:
216: <h2 id="obj">Device Object</h2>
217: <p>
218: The device object is created by the driver to communicate to the
219: application. Usually, the driver creates a device object for an existing
220: physical device. And, it can also be used to handle logical or virtual devices.
221: </p>
222:
223: <pre>
224: device_t device_create(const struct devio *io, const char *name, int flags);
225: int device_delete(device_t dev);
226: int device_broadcast(int event, int force);
227: </pre>
228:
229: <dl>
230: <dt>device_create()</dt>
231: <dd>
232: Creates device object with the specified name in <i>name</i>.
233: The <i>io</i> argument points to the device I/O table for the device object.
234: This function returns the ID of the created device object on success, or
235: 0 on failure.
236: <pre>
237: /*
238: * Device object
239: */
240: typedef int *device_t;
241: </pre>
242: All device object has its associated device I/O table. The table defines
243: the function pointer for the corresponding request routines.
244: <pre>
245: /*
246: * Device I/O table
247: */
248: struct devio {
249: int (*open)(device_t dev, int mode);
250: int (*close)(device_t dev);
251: int (*read)(device_t dev, char *buf, u_long *size, u_long offset);
252: int (*write)(device_t dev, char *buf, u_long *size, u_long offset);
253: int (*ioctl)(device_t dev, int cmd, u_long arg);
254: int (*event)(device_t dev, int event);
255: };
256: </pre>
257: The driver can specify the one same I/O table for the different device
258: objects. All device I/O routine can get the device object ID as its
259: first argument. So, each routine can determine the request is sent to
260: which device object.
261: </dd>
262: </dl>
263:
264: <dl>
265: <dt>device_delete()</dt>
266: <dd>
267: Deletes the device object specified in <i>dev</i>.
268: This function returns ENODEV if the specified device object does not exist.
269: </dd>
270: </dl>
271:
272: <dl>
273: <dt>device_broadcast()</dt>
274: <dd>
275: Broadcasts the message specified by <i>event</i> to all device objects.
276: If <i>force</i> is true, a kernel will ignore the value returned by
277: each driver, and continue event notification.
278: If <i>force</i> is false and any driver returns any error for the event,
279: a kernel stops the event notification. In this case, this function
280: returns an error code which is returned by that driver.
281: </dd>
282: </dl>
283:
284:
285: <h2 id="kmem">Kernel Memory</h2>
286: The kernel provides the following memory allocation services for drivers.
287: Please note that it can not allocate lager buffer than one page.
288: If the driver needs larger buffer, it should use page_alloc()
289: instead of kmem_alloc().
290: <pre>
291: void *kmem_alloc(size_t size);
292: void kmem_free(void *ptr);
293: void *kmem_map(void *addr, size_t size);
294: </pre>
295:
296: <dl>
297: <dt>kmem_alloc()</dt>
298: <dd>
299: Allocates the kernel buffer for the specified <i>size</i> bytes.
300: It returns the pointer to the allocated buffer on success, or NULL on failure.
301: </dd>
302: </dl>
303:
304: <dl>
305: <dt>kmem_free()</dt>
306: <dd>
307: Frees the allocated kernel buffer pointed by <i>ptr</i>.
308: </dd>
309: </dl>
310:
311: <dl>
312: <dt>kmem_map()</dt>
313: <dd>
314: Maps the specified virtual address <i>addr</i> to the kernel address.
315: It returns the pointer mapped in the kernel memory on success, or NULL if
316: there is no mapped memory.
317: </dd>
318: </dl>
319:
320: <h2 id="umem">User Memory</h2>
321: <p>
322: Since an access to user memory may cause a page fault, the user
323: buffer manipulation is handled by the kernel core code.
324: The driver should not access the user buffer directly. Instead,
325: it should use the following kernel services.
326: </p>
327: <pre>
328: int umem_copyin(void *uaddr, void *kaddr, size_t len);
329: int umem_copyout(void *kaddr, void *uaddr, size_t len);
330: int umem_strnlen(const char *uaddr, size_t maxlen, size_t *len);
331: </pre>
332:
333: <dl>
334: <dt>umem_copyin</dt>
335: <dd>
336: Copies the data from the user buffer to the kernel area.
337: Returns 0 on success, or EFAULT on failure.
338: </dd>
339: </dl>
340:
341: <dl>
342: <dt>umem_copyout</dt>
343: <dd>
344: Copies the data from the kernel buffer to the user area.
345: Returns 0 on success, or EFAULT on failure.
346: </dd>
347: </dl>
348:
349: <dl>
350: <dt>umem_strnlen</dt>
351: <dd>
352: Gets the length of specified string in <i>uaddr</i>.
353: Returns 0 on success, or EFAULT on failure.
354: The returned length does not include a NULL terminator.
355: </dd>
356: </dl>
357:
358: <h2 id="page">Physical Page</h2>
359: <pre>
360: void *page_alloc(u_long size);
361: void page_free(void *addr, u_long size);
362: int page_reserve(void *addr, u_long size);
363: </pre>
364:
365: <dl>
366: <dt>page_alloc()</dt>
367: <dd>
368: Allocates continuous pages for the specified <i>size</i> bytes.
369: This function returns the physical address of the allocated pages, or
370: returns NULL on failure. The kernel does not zero-fill this new page.
371: The requested size is automatically round up to the page boundary.
372: </dd>
373: </dl>
374:
375: <dl>
376: <dt>page_free()</dt>
377: <dd>
378: Frees allocated page block. The caller must provide the size information
379: in <i>size</i> argument that was specified for page_alloc().
380: </dd>
381: </dl>
382:
383: <dl>
384: <dt>page_reserve()</dt>
385: <dd>
386: Reserves pages in the specified address.
387: This function returns 0 on success, or -1 on failure.
388: </dd>
389: </dl>
390:
391:
392: <h2 id="int">Interrupt</h2>
393: <p>
394: The Prex kernel encapsulates the save/restore of the previous interrupt
395: state. irq_lock() will automatically save the previous interrupt state
396: if needed. So, the driver must call irq_unlock() for the same count of
397: the irq_lock() call.
398: </p>
399:
400: <pre>
401: int irq_attach(int irqno, int prio, int shared, int (*isr)(int), void (*ist)(int));
402: void irq_detach(int handle);
403: void irq_lock(void);
404: void irq_unlock(void);
405: </pre>
406:
407: <dl>
408: <dt>irq_attach()</dt>
409: <dd>
410: Attaches to the <i>ISR</i> (interrupt service request) and <i>ist</i>
411: (interrupt service thread) to the interrupt vector specified in <i>irqno</i>.
412: The argument <i>prio</i> is the logical interrupt priority level. The smaller
413: priority value is higher priority for interrupt processing.
414: The caller can specify one of the following interrupt priority levels.
415: <pre>
416: /*
417: * Interrupt priority levels
418: */
419: #define IPL_NONE 0 /* Nothing */
420: #define IPL_COMM 1 /* Serial, Parallel */
421: #define IPL_BLOCK 2 /* FDD, IDE */
422: #define IPL_NET 3 /* Network */
423: #define IPL_DISPLAY 4 /* Screen */
424: #define IPL_INPUT 5 /* Keyboard, Mouse */
425: #define IPL_AUDIO 6 /* Audio */
426: #define IPL_BUS 7 /* USB, PCCARD */
427: #define IPL_RTC 8 /* RTC Alarm */
428: #define IPL_PROFILE 9 /* Profiling timer */
429: #define IPL_CLOCK 10 /* System Clock Timer */
430: #define IPL_HIGH 11 /* Everything */
431: </pre>
432: If <i>shared</i> argument is true, the kernel allows the other irq owner
433: to attach to the same irq vector.
434: </dd>
435: </dl>
436:
437: <dl>
438: <dt>irq_detach()</dt>
439: <dd>
440: Detaches the interrupt from the IRQ specified by <i>handle</i>.
441: </dd>
442: </dl>
443:
444: <dl>
445: <dt>irq_lock()</dt>
446: <dd>
447: Masks all H/W interrupts, and increments the IRQ lock count.
448: </dd>
449: </dl>
450:
451: <dl>
452: <dt>irq_unlock()</dt>
453: <dd>
454: Decrements the IRQ lock count. If the IRQ lock count becomes 0,
455: the H/W interrupts are unmasked.
456: </dd>
457: </dl>
458:
459:
460: <h2 id="sched">Scheduler</h2>
461: <p>
462: The thread can sleep/wakeup for the specific event. The event works as
463: the queue of the sleeping threads.
464: </p>
465:
466: <pre>
467: void sched_lock(void);
468: void sched_unlock(void);
469: int sched_tsleep(struct event *evt, u_long timeout);
470: void sched_wakeup(struct event *evt);
471: void sched_dpc(struct dpc *dpc, void (*func)(void *), void *arg);
472: </pre>
473:
474: <dl>
475: <dt>sched_lock()</dt>
476: <dd>
477: Disables the thread switch, and increments the scheduling lock count.
478: This is used to synchronize the thread execution to protect
479: global resources. Since the scheduling lock count can be nested,
480: the caller must call the sched_unlock() routine the same number of
481: lock count.
482: </dd>
483: </dl>
484:
485: <dl>
486: <dt>sched_unlock()</dt>
487: <dd>
488: Decrements the scheduling lock count. If the scheduling lock count becomes 0,
489: the thread switch is enabled again.
490: </dd>
491: </dl>
492:
493: <dl>
494: <dt>sched_tsleep()</dt>
495: <dd>
496: Sleep the current thread until specified event occurs.
497: The caller can specify <i>timeout</i> value in msec.
498: If the <i>timeout</i> value is 0, the timeout timer does not work.
499: <pre>
500: /*
501: * Event for sleep/wakeup
502: */
503: struct event {
504: struct queue sleepq; /* Queue for waiting thread */
505: char *name; /* Event name */
506: };
507: </pre>
508: </dd>
509: </dl>
510:
511: <dl>
512: <dt>sched_wakeup()</dt>
513: <dd>
514: Wakes up all threads that are waiting for the specified event.
515: </dd>
516: </dl>
517:
518: <dl>
519: <dt>sched_dpc()</dt>
520: <dd>
521: Programs DPC (Deferred Procedure Call).
522: <pre>
523: /*
524: * DPC object
525: */
526: struct dpc {
527: struct queue link; /* Linkage on DPC queue */
528: int state;
529: void (*func)(void *); /* Call back routine */
530: void *arg; /* Argument to pass */
531: };
532: </pre>
533: </dd>
534: </dl>
535:
536: <h2 id="timer">Timer</h2>
537: <pre>
538: void timer_callout(struct timer *tmr, void (*func)(u_long), u_long arg, u_long msec);
539: void timer_stop(struct timer *tmr);
540: u_long timer_delay(u_long msec);
541: u_long timer_count(void);
542: int timer_hook(void (*func)(int));
543: </pre>
544:
545:
546: <dl>
547: <dt>timer_callout()</dt>
548: <dd>
549: Requests a call out timer. The specified <i>func</i> routine will be
550: called with <i>arg</i> argument after <i>msec</i>. The caller must
551: allocate the memory for the timer structure for <i>tmr</i>.
552: <pre>
553: /*
554: * Timer structure
555: */
556: struct timer {
557: struct list link; /* Linkage on timer chain */
558: int active; /* True if active */
559: u_long expire; /* Expire time (ticks) */
560: u_long interval; /* Time interval */
561: void (*func)(void *); /* Function to call */
562: void *arg; /* Function argument */
563: struct event event; /* Event for this timer */
564: };
565: </pre>
566: </dd>
567: </dl>
568:
569: <dl>
570: <dt>timer_stop()</dt>
571: <dd>
572: Stops a running timer.
573: </dd>
574: </dl>
575:
576: <dl>
577: <dt>timer_delay()</dt>
578: <dd>
579: Delays thread execution.
580: </dd>
581: </dl>
582:
583:
584: <dl>
585: <dt>timer_count()</dt>
586: <dd>
587: Returns current timer count (ticks since bootup).
588: </dd>
589: </dl>
590:
591: <dl>
592: <dt>timer_hook()</dt>
593: <dd>
594: Installs a hook routine for the timer tick.
595: </dd>
596: </dl>
597:
598:
599: <h2 id="misc">Miscellaneous</h2>
600: <pre>
601: int task_capable(task_t task);
602: int exception_post(task_t task, int exc);
603: void *phys_to_virt(void *p_addr);
604: void *virt_to_phys(void *v_addr);
605: void machine_reset(void);
606: void machine_dump(int index);
607: void debug_attach(void (*func)(char *));
608: void printk(const char *fmt, ...);
609: void panic(const char *fmt, ...);
610: </pre>
611:
612:
613: <dl>
614: <dt>task_capable()</dt>
615: <dd>
616: Checks the task capability for the speciifed item.
617: </dd>
618: </dl>
619:
620: <dl>
621: <dt>exception_post()</dt>
622: <dd>
623: Posts an exception for the specific task.
624: </dd>
625: </dl>
626:
627: <dl>
628: <dt>machine_reset()</dt>
629: <dd>
630: Resets the system.
631: </dd>
632: </dl>
633:
634: <dl>
635: <dt>machine_dump()</dt>
636: <dd>
637: Dumps the system information for debug.
638: </dd>
639: </dl>
640:
641: <dl>
642: <dt>phys_to_virt()</dt>
643: <dd>
644: Return the kernel virtual address from specifid physical address.
645: </dd>
646: </dl>
647:
648: <dl>
649: <dt>virt_to_phys()</dt>
650: <dd>
651: Return the mapped physical address from specifid virtual address.
652: </dd>
653: </dl>
654:
655: <dl>
656: <dt>debug_attach()</dt>
657: <dd>
658: Attaches to the external output routine for the printk().
659: </dd>
660: </dl>
661:
662: <dl>
663: <dt>printk()</dt>
664: <dd>
665: Prints the driver message to the output device.
666: The message is enabled only with debugging kernel.
667: </dd>
668: </dl>
669:
670: <dl>
671: <dt>panic()</dt>
672: <dd>
673: Stops the system for the fatal error.
674: </dd>
675: </dl>
676:
677:
678: </td>
679: </tr>
680: <tr>
681: <td id="footer" colspan="2" style="vertical-align: top;">
682: <a href="http://sourceforge.net">
683: <img src="http://sourceforge.net/sflogo.php?group_id=132028&type=1"
684: alt="SourceForge.net Logo" border="0" height="31" width="88"></a><br>
685: Copyright© 2005-2007 Kohsuke Ohtani
686: </td>
687: </tr>
688:
689: </tbody>
690: </table>
691:
692: </div>
693: <div id="bottom"></div>
694:
695: </body>
696: </html>
CVSweb