Intel MID PTI

The Intel MID PTI project is HW implemented in Intel Atomsystem-on-a-chip designs based on the Parallel TraceInterface for MIPI P1149.7 cJTAG standard. The kernel solutionfor this platform involves the following files:

./include/linux/pti.h./drivers/.../n_tracesink.h./drivers/.../n_tracerouter.c./drivers/.../n_tracesink.c./drivers/.../pti.c

pti.c is the driver that enables various debugging featurespopular on platforms from certain mobile manufacturers.n_tracerouter.c and n_tracesink.c allow extra system information tobe collected and routed to the pti driver, such as tracedebugging data from a modem. Although n_tracerouterand n_tracesink are a part of the complete PTI solution,these two line disciplines can work separately frompti.c and route any data stream from one /dev/tty nodeto another /dev/tty node via kernel-space. This providesa stable, reliable connection that will not break unlessthe user-space application shuts down (plus avoidskernel->user->kernel context switch overheads of routingdata).

An example debugging usage for this driver system:

  • Hook /dev/ttyPTI0 to syslogd. Opening this port will also starta console device to further capture debugging messages to PTI.
  • Hook /dev/ttyPTI1 to modem debugging data to write to PTI HW.This is where n_tracerouter and n_tracesink are used.
  • Hook /dev/pti to a user-level debugging application for writingto PTI HW.
  • Use mipi_ Kernel Driver API in other device drivers fordebugging to PTI by first requesting a PTI write address viamipi_request_masterchannel(1).

Below is example pseudo-code on how a ‘privileged’ applicationcan hook up n_tracerouter and n_tracesink to any tty ona system. ‘Privileged’ means the application has enoughprivileges to successfully manipulate the ldisc driversbut is not just blindly executing as ‘root’. Keep in mindthe use of ioctl(,TIOCSETD,) is not specific to the n_tracerouterand n_tracesink line discpline drivers but is a genericoperation for a program to use a line discpline driveron a tty port other than the default n_tty:

/////////// To hook up n_tracerouter and n_tracesink /////////// Note that n_tracerouter depends on n_tracesink.#include<errno.h>#define ONE_TTY "/dev/ttyOne"#define TWO_TTY "/dev/ttyTwo"// needed global to hand onto ldisc connectionstaticintg_fd_source=-1;staticintg_fd_sink=-1;// these two vars used to grab LDISC values from loaded ldisc drivers// in OS.  Look at /proc/tty/ldiscs to get the right numbers from// the ldiscs loaded in the system.intsource_ldisc_num,sink_ldisc_num=-1;intretval;g_fd_source=open(ONE_TTY,O_RDWR);// must be R/Wg_fd_sink=open(TWO_TTY,O_RDWR);// must be R/Wif(g_fd_source<=0)||(g_fd_sink<=0){// doubt you'll want to use these exact error lines of codeprintf("Error on open(). errno: %d\n",errno);returnerrno;}retval=ioctl(g_fd_sink,TIOCSETD,&sink_ldisc_num);if(retval<0){printf("Error on ioctl().  errno: %d\n",errno);returnerrno;}retval=ioctl(g_fd_source,TIOCSETD,&source_ldisc_num);if(retval<0){printf("Error on ioctl().  errno: %d\n",errno);returnerrno;}/////////// To disconnect n_tracerouter and n_tracesink ////////// First make sure data through the ldiscs has stopped.// Second, disconnect ldiscs.  This provides a// little cleaner shutdown on tty stack.sink_ldisc_num=0;source_ldisc_num=0;ioctl(g_fd_uart,TIOCSETD,&sink_ldisc_num);ioctl(g_fd_gadget,TIOCSETD,&source_ldisc_num);// Three, program closes connection, and cleanup:close(g_fd_uart);close(g_fd_gadget);g_fd_uart=g_fd_gadget=NULL;