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