J Freyensee | cb9e84c | 2011-05-06 16:56:48 -0700 | [diff] [blame] | 1 | The Intel MID PTI project is HW implemented in Intel Atom |
| 2 | system-on-a-chip designs based on the Parallel Trace |
| 3 | Interface for MIPI P1149.7 cJTAG standard. The kernel solution |
| 4 | for this platform involves the following files: |
| 5 | |
| 6 | ./include/linux/pti.h |
| 7 | ./drivers/.../n_tracesink.h |
| 8 | ./drivers/.../n_tracerouter.c |
| 9 | ./drivers/.../n_tracesink.c |
| 10 | ./drivers/.../pti.c |
| 11 | |
| 12 | pti.c is the driver that enables various debugging features |
| 13 | popular on platforms from certain mobile manufacturers. |
| 14 | n_tracerouter.c and n_tracesink.c allow extra system information to |
| 15 | be collected and routed to the pti driver, such as trace |
| 16 | debugging data from a modem. Although n_tracerouter |
| 17 | and n_tracesink are a part of the complete PTI solution, |
| 18 | these two line disciplines can work separately from |
| 19 | pti.c and route any data stream from one /dev/tty node |
| 20 | to another /dev/tty node via kernel-space. This provides |
| 21 | a stable, reliable connection that will not break unless |
| 22 | the user-space application shuts down (plus avoids |
| 23 | kernel->user->kernel context switch overheads of routing |
| 24 | data). |
| 25 | |
| 26 | An example debugging usage for this driver system: |
| 27 | *Hook /dev/ttyPTI0 to syslogd. Opening this port will also start |
| 28 | a console device to further capture debugging messages to PTI. |
| 29 | *Hook /dev/ttyPTI1 to modem debugging data to write to PTI HW. |
| 30 | This is where n_tracerouter and n_tracesink are used. |
| 31 | *Hook /dev/pti to a user-level debugging application for writing |
| 32 | to PTI HW. |
| 33 | *Use mipi_* Kernel Driver API in other device drivers for |
| 34 | debugging to PTI by first requesting a PTI write address via |
| 35 | mipi_request_masterchannel(1). |
| 36 | |
| 37 | Below is example pseudo-code on how a 'privileged' application |
| 38 | can hook up n_tracerouter and n_tracesink to any tty on |
| 39 | a system. 'Privileged' means the application has enough |
| 40 | privileges to successfully manipulate the ldisc drivers |
| 41 | but is not just blindly executing as 'root'. Keep in mind |
| 42 | the use of ioctl(,TIOCSETD,) is not specific to the n_tracerouter |
| 43 | and n_tracesink line discpline drivers but is a generic |
| 44 | operation for a program to use a line discpline driver |
| 45 | on a tty port other than the default n_tty. |
| 46 | |
| 47 | /////////// To hook up n_tracerouter and n_tracesink ///////// |
| 48 | |
| 49 | // Note that n_tracerouter depends on n_tracesink. |
| 50 | #include <errno.h> |
| 51 | #define ONE_TTY "/dev/ttyOne" |
| 52 | #define TWO_TTY "/dev/ttyTwo" |
| 53 | |
| 54 | // needed global to hand onto ldisc connection |
| 55 | static int g_fd_source = -1; |
| 56 | static int g_fd_sink = -1; |
| 57 | |
| 58 | // these two vars used to grab LDISC values from loaded ldisc drivers |
| 59 | // in OS. Look at /proc/tty/ldiscs to get the right numbers from |
| 60 | // the ldiscs loaded in the system. |
| 61 | int source_ldisc_num, sink_ldisc_num = -1; |
| 62 | int retval; |
| 63 | |
| 64 | g_fd_source = open(ONE_TTY, O_RDWR); // must be R/W |
| 65 | g_fd_sink = open(TWO_TTY, O_RDWR); // must be R/W |
| 66 | |
| 67 | if (g_fd_source <= 0) || (g_fd_sink <= 0) { |
| 68 | // doubt you'll want to use these exact error lines of code |
| 69 | printf("Error on open(). errno: %d\n",errno); |
| 70 | return errno; |
| 71 | } |
| 72 | |
| 73 | retval = ioctl(g_fd_sink, TIOCSETD, &sink_ldisc_num); |
| 74 | if (retval < 0) { |
| 75 | printf("Error on ioctl(). errno: %d\n", errno); |
| 76 | return errno; |
| 77 | } |
| 78 | |
| 79 | retval = ioctl(g_fd_source, TIOCSETD, &source_ldisc_num); |
| 80 | if (retval < 0) { |
| 81 | printf("Error on ioctl(). errno: %d\n", errno); |
| 82 | return errno; |
| 83 | } |
| 84 | |
| 85 | /////////// To disconnect n_tracerouter and n_tracesink //////// |
| 86 | |
| 87 | // First make sure data through the ldiscs has stopped. |
| 88 | |
| 89 | // Second, disconnect ldiscs. This provides a |
| 90 | // little cleaner shutdown on tty stack. |
| 91 | sink_ldisc_num = 0; |
| 92 | source_ldisc_num = 0; |
| 93 | ioctl(g_fd_uart, TIOCSETD, &sink_ldisc_num); |
| 94 | ioctl(g_fd_gadget, TIOCSETD, &source_ldisc_num); |
| 95 | |
| 96 | // Three, program closes connection, and cleanup: |
| 97 | close(g_fd_uart); |
| 98 | close(g_fd_gadget); |
| 99 | g_fd_uart = g_fd_gadget = NULL; |