aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorJ Freyensee <james_p_freyensee@linux.intel.com>2011-05-06 19:56:49 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-05-13 19:31:00 -0400
commit0b61d2acb1ea48d8eba798ed92759b7f1b0f4209 (patch)
tree48827990afa819f2a81929450c69b39aa8255c4d /drivers/misc
parentcb9e84c4123088f4641009f5217b7d32b307992f (diff)
Intel PTI implementaiton of MIPI 1149.7.
The PTI (Parallel Trace Interface) driver directs trace data routed from various parts in the system out through an Intel Penwell PTI port and out of the mobile device for analysis with a debugging tool (Lauterbach or Fido). Though n_tracesink and n_tracerouter line discipline drivers are used to extract modem tracing data to the PTI driver and other parts of an Intel mobile solution, the PTI driver can be used independent of n_tracesink and n_tracerouter. You should select this driver if the target kernel is meant for an Intel Atom (non-netbook) mobile device containing a MIPI P1149.7 standard implementation. Signed-off-by: J Freyensee <james_p_freyensee@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig13
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/pti.c980
3 files changed, 994 insertions, 0 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 915c31ef84cd..ec33d939548c 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -144,6 +144,19 @@ config PHANTOM
144 If you choose to build module, its name will be phantom. If unsure, 144 If you choose to build module, its name will be phantom. If unsure,
145 say N here. 145 say N here.
146 146
147config INTEL_MID_PTI
148 tristate "Parallel Trace Interface for MIPI P1149.7 cJTAG standard"
149 default n
150 help
151 The PTI (Parallel Trace Interface) driver directs
152 trace data routed from various parts in the system out
153 through an Intel Penwell PTI port and out of the mobile
154 device for analysis with a debugging tool (Lauterbach or Fido).
155
156 You should select this driver if the target kernel is meant for
157 an Intel Atom (non-netbook) mobile device containing a MIPI
158 P1149.7 standard implementation.
159
147config SGI_IOC4 160config SGI_IOC4
148 tristate "SGI IOC4 Base IO support" 161 tristate "SGI IOC4 Base IO support"
149 depends on PCI 162 depends on PCI
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f5468602961f..662aa3c71d05 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_IBM_ASM) += ibmasm/
6obj-$(CONFIG_AD525X_DPOT) += ad525x_dpot.o 6obj-$(CONFIG_AD525X_DPOT) += ad525x_dpot.o
7obj-$(CONFIG_AD525X_DPOT_I2C) += ad525x_dpot-i2c.o 7obj-$(CONFIG_AD525X_DPOT_I2C) += ad525x_dpot-i2c.o
8obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o 8obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o
90bj-$(CONFIG_INTEL_MID_PTI) += pti.o
9obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o 10obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
10obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o 11obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
11obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o 12obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
new file mode 100644
index 000000000000..bb6f9255c17c
--- /dev/null
+++ b/drivers/misc/pti.c
@@ -0,0 +1,980 @@
1/*
2 * pti.c - PTI driver for cJTAG data extration
3 *
4 * Copyright (C) Intel 2010
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16 *
17 * The PTI (Parallel Trace Interface) driver directs trace data routed from
18 * various parts in the system out through the Intel Penwell PTI port and
19 * out of the mobile device for analysis with a debugging tool
20 * (Lauterbach, Fido). This is part of a solution for the MIPI P1149.7,
21 * compact JTAG, standard.
22 */
23
24#include <linux/init.h>
25#include <linux/sched.h>
26#include <linux/interrupt.h>
27#include <linux/console.h>
28#include <linux/kernel.h>
29#include <linux/module.h>
30#include <linux/tty.h>
31#include <linux/tty_driver.h>
32#include <linux/pci.h>
33#include <linux/mutex.h>
34#include <linux/miscdevice.h>
35#include <linux/pti.h>
36
37#define DRIVERNAME "pti"
38#define PCINAME "pciPTI"
39#define TTYNAME "ttyPTI"
40#define CHARNAME "pti"
41#define PTITTY_MINOR_START 0
42#define PTITTY_MINOR_NUM 2
43#define MAX_APP_IDS 16 /* 128 channel ids / u8 bit size */
44#define MAX_OS_IDS 16 /* 128 channel ids / u8 bit size */
45#define MAX_MODEM_IDS 16 /* 128 channel ids / u8 bit size */
46#define MODEM_BASE_ID 71 /* modem master ID address */
47#define CONTROL_ID 72 /* control master ID address */
48#define CONSOLE_ID 73 /* console master ID address */
49#define OS_BASE_ID 74 /* base OS master ID address */
50#define APP_BASE_ID 80 /* base App master ID address */
51#define CONTROL_FRAME_LEN 32 /* PTI control frame maximum size */
52#define USER_COPY_SIZE 8192 /* 8Kb buffer for user space copy */
53#define APERTURE_14 0x3800000 /* offset to first OS write addr */
54#define APERTURE_LEN 0x400000 /* address length */
55
56struct pti_tty {
57 struct pti_masterchannel *mc;
58};
59
60struct pti_dev {
61 struct tty_port port;
62 unsigned long pti_addr;
63 unsigned long aperture_base;
64 void __iomem *pti_ioaddr;
65 u8 ia_app[MAX_APP_IDS];
66 u8 ia_os[MAX_OS_IDS];
67 u8 ia_modem[MAX_MODEM_IDS];
68};
69
70/*
71 * This protects access to ia_app, ia_os, and ia_modem,
72 * which keeps track of channels allocated in
73 * an aperture write id.
74 */
75static DEFINE_MUTEX(alloclock);
76
77static struct pci_device_id pci_ids[] __devinitconst = {
78 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x82B)},
79 {0}
80};
81
82static struct tty_driver *pti_tty_driver;
83static struct pti_dev *drv_data;
84
85static unsigned int pti_console_channel;
86static unsigned int pti_control_channel;
87
88/**
89 * pti_write_to_aperture()- The private write function to PTI HW.
90 *
91 * @mc: The 'aperture'. It's part of a write address that holds
92 * a master and channel ID.
93 * @buf: Data being written to the HW that will ultimately be seen
94 * in a debugging tool (Fido, Lauterbach).
95 * @len: Size of buffer.
96 *
97 * Since each aperture is specified by a unique
98 * master/channel ID, no two processes will be writing
99 * to the same aperture at the same time so no lock is required. The
100 * PTI-Output agent will send these out in the order that they arrived, and
101 * thus, it will intermix these messages. The debug tool can then later
102 * regroup the appropriate message segments together reconstituting each
103 * message.
104 */
105static void pti_write_to_aperture(struct pti_masterchannel *mc,
106 u8 *buf,
107 int len)
108{
109 int dwordcnt;
110 int final;
111 int i;
112 u32 ptiword;
113 u32 __iomem *aperture;
114 u8 *p = buf;
115
116 /*
117 * calculate the aperture offset from the base using the master and
118 * channel id's.
119 */
120 aperture = drv_data->pti_ioaddr + (mc->master << 15)
121 + (mc->channel << 8);
122
123 dwordcnt = len >> 2;
124 final = len - (dwordcnt << 2); /* final = trailing bytes */
125 if (final == 0 && dwordcnt != 0) { /* always need a final dword */
126 final += 4;
127 dwordcnt--;
128 }
129
130 for (i = 0; i < dwordcnt; i++) {
131 ptiword = be32_to_cpu(*(u32 *)p);
132 p += 4;
133 iowrite32(ptiword, aperture);
134 }
135
136 aperture += PTI_LASTDWORD_DTS; /* adding DTS signals that is EOM */
137
138 ptiword = 0;
139 for (i = 0; i < final; i++)
140 ptiword |= *p++ << (24-(8*i));
141
142 iowrite32(ptiword, aperture);
143 return;
144}
145
146/**
147 * pti_control_frame_built_and_sent()- control frame build and send function.
148 *
149 * @mc: The master / channel structure on which the function
150 * built a control frame.
151 *
152 * To be able to post process the PTI contents on host side, a control frame
153 * is added before sending any PTI content. So the host side knows on
154 * each PTI frame the name of the thread using a dedicated master / channel.
155 * The thread name is retrieved from the 'current' global variable.
156 * This function builds this frame and sends it to a master ID CONTROL_ID.
157 * The overhead is only 32 bytes since the driver only writes to HW
158 * in 32 byte chunks.
159 */
160
161static void pti_control_frame_built_and_sent(struct pti_masterchannel *mc)
162{
163 struct pti_masterchannel mccontrol = {.master = CONTROL_ID,
164 .channel = 0};
165 const char *control_format = "%3d %3d %s";
166 u8 control_frame[CONTROL_FRAME_LEN];
167
168 /*
169 * Since we access the comm member in current's task_struct,
170 * we only need to be as large as what 'comm' in that
171 * structure is.
172 */
173 char comm[TASK_COMM_LEN];
174
175 if (!in_interrupt())
176 get_task_comm(comm, current);
177 else
178 strncpy(comm, "Interrupt", TASK_COMM_LEN);
179
180 /* Absolutely ensure our buffer is zero terminated. */
181 comm[TASK_COMM_LEN-1] = 0;
182
183 mccontrol.channel = pti_control_channel;
184 pti_control_channel = (pti_control_channel + 1) & 0x7f;
185
186 snprintf(control_frame, CONTROL_FRAME_LEN, control_format, mc->master,
187 mc->channel, comm);
188 pti_write_to_aperture(&mccontrol, control_frame, strlen(control_frame));
189}
190
191/**
192 * pti_write_full_frame_to_aperture()- high level function to
193 * write to PTI.
194 *
195 * @mc: The 'aperture'. It's part of a write address that holds
196 * a master and channel ID.
197 * @buf: Data being written to the HW that will ultimately be seen
198 * in a debugging tool (Fido, Lauterbach).
199 * @len: Size of buffer.
200 *
201 * All threads sending data (either console, user space application, ...)
202 * are calling the high level function to write to PTI meaning that it is
203 * possible to add a control frame before sending the content.
204 */
205static void pti_write_full_frame_to_aperture(struct pti_masterchannel *mc,
206 const unsigned char *buf,
207 int len)
208{
209 pti_control_frame_built_and_sent(mc);
210 pti_write_to_aperture(mc, (u8 *)buf, len);
211}
212
213/**
214 * get_id()- Allocate a master and channel ID.
215 *
216 * @id_array: an array of bits representing what channel
217 * id's are allocated for writing.
218 * @max_ids: The max amount of available write IDs to use.
219 * @base_id: The starting SW channel ID, based on the Intel
220 * PTI arch.
221 *
222 * Returns:
223 * pti_masterchannel struct with master, channel ID address
224 * 0 for error
225 *
226 * Each bit in the arrays ia_app and ia_os correspond to a master and
227 * channel id. The bit is one if the id is taken and 0 if free. For
228 * every master there are 128 channel id's.
229 */
230static struct pti_masterchannel *get_id(u8 *id_array, int max_ids, int base_id)
231{
232 struct pti_masterchannel *mc;
233 int i, j, mask;
234
235 mc = kmalloc(sizeof(struct pti_masterchannel), GFP_KERNEL);
236 if (mc == NULL)
237 return NULL;
238
239 /* look for a byte with a free bit */
240 for (i = 0; i < max_ids; i++)
241 if (id_array[i] != 0xff)
242 break;
243 if (i == max_ids) {
244 kfree(mc);
245 return NULL;
246 }
247 /* find the bit in the 128 possible channel opportunities */
248 mask = 0x80;
249 for (j = 0; j < 8; j++) {
250 if ((id_array[i] & mask) == 0)
251 break;
252 mask >>= 1;
253 }
254
255 /* grab it */
256 id_array[i] |= mask;
257 mc->master = base_id;
258 mc->channel = ((i & 0xf)<<3) + j;
259 /* write new master Id / channel Id allocation to channel control */
260 pti_control_frame_built_and_sent(mc);
261 return mc;
262}
263
264/*
265 * The following three functions:
266 * pti_request_mastercahannel(), mipi_release_masterchannel()
267 * and pti_writedata() are an API for other kernel drivers to
268 * access PTI.
269 */
270
271/**
272 * pti_request_masterchannel()- Kernel API function used to allocate
273 * a master, channel ID address
274 * to write to PTI HW.
275 *
276 * @type: 0- request Application master, channel aperture ID write address.
277 * 1- request OS master, channel aperture ID write
278 * address.
279 * 2- request Modem master, channel aperture ID
280 * write address.
281 * Other values, error.
282 *
283 * Returns:
284 * pti_masterchannel struct
285 * 0 for error
286 */
287struct pti_masterchannel *pti_request_masterchannel(u8 type)
288{
289 struct pti_masterchannel *mc;
290
291 mutex_lock(&alloclock);
292
293 switch (type) {
294
295 case 0:
296 mc = get_id(drv_data->ia_app, MAX_APP_IDS, APP_BASE_ID);
297 break;
298
299 case 1:
300 mc = get_id(drv_data->ia_os, MAX_OS_IDS, OS_BASE_ID);
301 break;
302
303 case 2:
304 mc = get_id(drv_data->ia_modem, MAX_MODEM_IDS, MODEM_BASE_ID);
305 break;
306 default:
307 mc = NULL;
308 }
309
310 mutex_unlock(&alloclock);
311 return mc;
312}
313EXPORT_SYMBOL_GPL(pti_request_masterchannel);
314
315/**
316 * pti_release_masterchannel()- Kernel API function used to release
317 * a master, channel ID address
318 * used to write to PTI HW.
319 *
320 * @mc: master, channel apeture ID address to be released.
321 */
322void pti_release_masterchannel(struct pti_masterchannel *mc)
323{
324 u8 master, channel, i;
325
326 mutex_lock(&alloclock);
327
328 if (mc) {
329 master = mc->master;
330 channel = mc->channel;
331
332 if (master == APP_BASE_ID) {
333 i = channel >> 3;
334 drv_data->ia_app[i] &= ~(0x80>>(channel & 0x7));
335 } else if (master == OS_BASE_ID) {
336 i = channel >> 3;
337 drv_data->ia_os[i] &= ~(0x80>>(channel & 0x7));
338 } else {
339 i = channel >> 3;
340 drv_data->ia_modem[i] &= ~(0x80>>(channel & 0x7));
341 }
342
343 kfree(mc);
344 }
345
346 mutex_unlock(&alloclock);
347}
348EXPORT_SYMBOL_GPL(pti_release_masterchannel);
349
350/**
351 * pti_writedata()- Kernel API function used to write trace
352 * debugging data to PTI HW.
353 *
354 * @mc: Master, channel aperture ID address to write to.
355 * Null value will return with no write occurring.
356 * @buf: Trace debuging data to write to the PTI HW.
357 * Null value will return with no write occurring.
358 * @count: Size of buf. Value of 0 or a negative number will
359 * return with no write occuring.
360 */
361void pti_writedata(struct pti_masterchannel *mc, u8 *buf, int count)
362{
363 /*
364 * since this function is exported, this is treated like an
365 * API function, thus, all parameters should
366 * be checked for validity.
367 */
368 if ((mc != NULL) && (buf != NULL) && (count > 0))
369 pti_write_to_aperture(mc, buf, count);
370 return;
371}
372EXPORT_SYMBOL_GPL(pti_writedata);
373
374/**
375 * pti_pci_remove()- Driver exit method to remove PTI from
376 * PCI bus.
377 * @pdev: variable containing pci info of PTI.
378 */
379static void __devexit pti_pci_remove(struct pci_dev *pdev)
380{
381 struct pti_dev *drv_data;
382
383 drv_data = pci_get_drvdata(pdev);
384 if (drv_data != NULL) {
385 pci_iounmap(pdev, drv_data->pti_ioaddr);
386 pci_set_drvdata(pdev, NULL);
387 kfree(drv_data);
388 pci_release_region(pdev, 1);
389 pci_disable_device(pdev);
390 }
391}
392
393/*
394 * for the tty_driver_*() basic function descriptions, see tty_driver.h.
395 * Specific header comments made for PTI-related specifics.
396 */
397
398/**
399 * pti_tty_driver_open()- Open an Application master, channel aperture
400 * ID to the PTI device via tty device.
401 *
402 * @tty: tty interface.
403 * @filp: filp interface pased to tty_port_open() call.
404 *
405 * Returns:
406 * int, 0 for success
407 * otherwise, fail value
408 *
409 * The main purpose of using the tty device interface is for
410 * each tty port to have a unique PTI write aperture. In an
411 * example use case, ttyPTI0 gets syslogd and an APP aperture
412 * ID and ttyPTI1 is where the n_tracesink ldisc hooks to route
413 * modem messages into PTI. Modem trace data does not have to
414 * go to ttyPTI1, but ttyPTI0 and ttyPTI1 do need to be distinct
415 * master IDs. These messages go through the PTI HW and out of
416 * the handheld platform and to the Fido/Lauterbach device.
417 */
418static int pti_tty_driver_open(struct tty_struct *tty, struct file *filp)
419{
420 /*
421 * we actually want to allocate a new channel per open, per
422 * system arch. HW gives more than plenty channels for a single
423 * system task to have its own channel to write trace data. This
424 * also removes a locking requirement for the actual write
425 * procedure.
426 */
427 return tty_port_open(&drv_data->port, tty, filp);
428}
429
430/**
431 * pti_tty_driver_close()- close tty device and release Application
432 * master, channel aperture ID to the PTI device via tty device.
433 *
434 * @tty: tty interface.
435 * @filp: filp interface pased to tty_port_close() call.
436 *
437 * The main purpose of using the tty device interface is to route
438 * syslog daemon messages to the PTI HW and out of the handheld platform
439 * and to the Fido/Lauterbach device.
440 */
441static void pti_tty_driver_close(struct tty_struct *tty, struct file *filp)
442{
443 tty_port_close(&drv_data->port, tty, filp);
444}
445
446/**
447 * pti_tty_intstall()- Used to set up specific master-channels
448 * to tty ports for organizational purposes when
449 * tracing viewed from debuging tools.
450 *
451 * @driver: tty driver information.
452 * @tty: tty struct containing pti information.
453 *
454 * Returns:
455 * 0 for success
456 * otherwise, error
457 */
458static int pti_tty_install(struct tty_driver *driver, struct tty_struct *tty)
459{
460 int idx = tty->index;
461 struct pti_tty *pti_tty_data;
462 int ret = tty_init_termios(tty);
463
464 if (ret == 0) {
465 tty_driver_kref_get(driver);
466 tty->count++;
467 driver->ttys[idx] = tty;
468
469 pti_tty_data = kmalloc(sizeof(struct pti_tty), GFP_KERNEL);
470 if (pti_tty_data == NULL)
471 return -ENOMEM;
472
473 if (idx == PTITTY_MINOR_START)
474 pti_tty_data->mc = pti_request_masterchannel(0);
475 else
476 pti_tty_data->mc = pti_request_masterchannel(2);
477
478 if (pti_tty_data->mc == NULL)
479 return -ENXIO;
480 tty->driver_data = pti_tty_data;
481 }
482
483 return ret;
484}
485
486/**
487 * pti_tty_cleanup()- Used to de-allocate master-channel resources
488 * tied to tty's of this driver.
489 *
490 * @tty: tty struct containing pti information.
491 */
492static void pti_tty_cleanup(struct tty_struct *tty)
493{
494 struct pti_tty *pti_tty_data = tty->driver_data;
495 if (pti_tty_data == NULL)
496 return;
497 pti_release_masterchannel(pti_tty_data->mc);
498 kfree(tty->driver_data);
499 tty->driver_data = NULL;
500}
501
502/**
503 * pti_tty_driver_write()- Write trace debugging data through the char
504 * interface to the PTI HW. Part of the misc device implementation.
505 *
506 * @filp: Contains private data which is used to obtain
507 * master, channel write ID.
508 * @data: trace data to be written.
509 * @len: # of byte to write.
510 *
511 * Returns:
512 * int, # of bytes written
513 * otherwise, error
514 */
515static int pti_tty_driver_write(struct tty_struct *tty,
516 const unsigned char *buf, int len)
517{
518 struct pti_tty *pti_tty_data = tty->driver_data;
519 if ((pti_tty_data != NULL) && (pti_tty_data->mc != NULL)) {
520 pti_write_to_aperture(pti_tty_data->mc, (u8 *)buf, len);
521 return len;
522 }
523 /*
524 * we can't write to the pti hardware if the private driver_data
525 * and the mc address is not there.
526 */
527 else
528 return -EFAULT;
529}
530
531/**
532 * pti_tty_write_room()- Always returns 2048.
533 *
534 * @tty: contains tty info of the pti driver.
535 */
536static int pti_tty_write_room(struct tty_struct *tty)
537{
538 return 2048;
539}
540
541/**
542 * pti_char_open()- Open an Application master, channel aperture
543 * ID to the PTI device. Part of the misc device implementation.
544 *
545 * @inode: not used.
546 * @filp: Output- will have a masterchannel struct set containing
547 * the allocated application PTI aperture write address.
548 *
549 * Returns:
550 * int, 0 for success
551 * otherwise, a fail value
552 */
553static int pti_char_open(struct inode *inode, struct file *filp)
554{
555 struct pti_masterchannel *mc;
556
557 /*
558 * We really do want to fail immediately if
559 * pti_request_masterchannel() fails,
560 * before assigning the value to filp->private_data.
561 * Slightly easier to debug if this driver needs debugging.
562 */
563 mc = pti_request_masterchannel(0);
564 if (mc == NULL)
565 return -ENOMEM;
566 filp->private_data = mc;
567 return 0;
568}
569
570/**
571 * pti_char_release()- Close a char channel to the PTI device. Part
572 * of the misc device implementation.
573 *
574 * @inode: Not used in this implementaiton.
575 * @filp: Contains private_data that contains the master, channel
576 * ID to be released by the PTI device.
577 *
578 * Returns:
579 * always 0
580 */
581static int pti_char_release(struct inode *inode, struct file *filp)
582{
583 pti_release_masterchannel(filp->private_data);
584 kfree(filp->private_data);
585 return 0;
586}
587
588/**
589 * pti_char_write()- Write trace debugging data through the char
590 * interface to the PTI HW. Part of the misc device implementation.
591 *
592 * @filp: Contains private data which is used to obtain
593 * master, channel write ID.
594 * @data: trace data to be written.
595 * @len: # of byte to write.
596 * @ppose: Not used in this function implementation.
597 *
598 * Returns:
599 * int, # of bytes written
600 * otherwise, error value
601 *
602 * Notes: From side discussions with Alan Cox and experimenting
603 * with PTI debug HW like Nokia's Fido box and Lauterbach
604 * devices, 8192 byte write buffer used by USER_COPY_SIZE was
605 * deemed an appropriate size for this type of usage with
606 * debugging HW.
607 */
608static ssize_t pti_char_write(struct file *filp, const char __user *data,
609 size_t len, loff_t *ppose)
610{
611 struct pti_masterchannel *mc;
612 void *kbuf;
613 const char __user *tmp;
614 size_t size = USER_COPY_SIZE;
615 size_t n = 0;
616
617 tmp = data;
618 mc = filp->private_data;
619
620 kbuf = kmalloc(size, GFP_KERNEL);
621 if (kbuf == NULL) {
622 pr_err("%s(%d): buf allocation failed\n",
623 __func__, __LINE__);
624 return -ENOMEM;
625 }
626
627 do {
628 if (len - n > USER_COPY_SIZE)
629 size = USER_COPY_SIZE;
630 else
631 size = len - n;
632
633 if (copy_from_user(kbuf, tmp, size)) {
634 kfree(kbuf);
635 return n ? n : -EFAULT;
636 }
637
638 pti_write_to_aperture(mc, kbuf, size);
639 n += size;
640 tmp += size;
641
642 } while (len > n);
643
644 kfree(kbuf);
645 return len;
646}
647
648static const struct tty_operations pti_tty_driver_ops = {
649 .open = pti_tty_driver_open,
650 .close = pti_tty_driver_close,
651 .write = pti_tty_driver_write,
652 .write_room = pti_tty_write_room,
653 .install = pti_tty_install,
654 .cleanup = pti_tty_cleanup
655};
656
657static const struct file_operations pti_char_driver_ops = {
658 .owner = THIS_MODULE,
659 .write = pti_char_write,
660 .open = pti_char_open,
661 .release = pti_char_release,
662};
663
664static struct miscdevice pti_char_driver = {
665 .minor = MISC_DYNAMIC_MINOR,
666 .name = CHARNAME,
667 .fops = &pti_char_driver_ops
668};
669
670/**
671 * pti_console_write()- Write to the console that has been acquired.
672 *
673 * @c: Not used in this implementaiton.
674 * @buf: Data to be written.
675 * @len: Length of buf.
676 */
677static void pti_console_write(struct console *c, const char *buf, unsigned len)
678{
679 static struct pti_masterchannel mc = {.master = CONSOLE_ID,
680 .channel = 0};
681
682 mc.channel = pti_console_channel;
683 pti_console_channel = (pti_console_channel + 1) & 0x7f;
684
685 pti_write_full_frame_to_aperture(&mc, buf, len);
686}
687
688/**
689 * pti_console_device()- Return the driver tty structure and set the
690 * associated index implementation.
691 *
692 * @c: Console device of the driver.
693 * @index: index associated with c.
694 *
695 * Returns:
696 * always value of pti_tty_driver structure when this function
697 * is called.
698 */
699static struct tty_driver *pti_console_device(struct console *c, int *index)
700{
701 *index = c->index;
702 return pti_tty_driver;
703}
704
705/**
706 * pti_console_setup()- Initialize console variables used by the driver.
707 *
708 * @c: Not used.
709 * @opts: Not used.
710 *
711 * Returns:
712 * always 0.
713 */
714static int pti_console_setup(struct console *c, char *opts)
715{
716 pti_console_channel = 0;
717 pti_control_channel = 0;
718 return 0;
719}
720
721/*
722 * pti_console struct, used to capture OS printk()'s and shift
723 * out to the PTI device for debugging. This cannot be
724 * enabled upon boot because of the possibility of eating
725 * any serial console printk's (race condition discovered).
726 * The console should be enabled upon when the tty port is
727 * used for the first time. Since the primary purpose for
728 * the tty port is to hook up syslog to it, the tty port
729 * will be open for a really long time.
730 */
731static struct console pti_console = {
732 .name = TTYNAME,
733 .write = pti_console_write,
734 .device = pti_console_device,
735 .setup = pti_console_setup,
736 .flags = CON_PRINTBUFFER,
737 .index = 0,
738};
739
740/**
741 * pti_port_activate()- Used to start/initialize any items upon
742 * first opening of tty_port().
743 *
744 * @port- The tty port number of the PTI device.
745 * @tty- The tty struct associated with this device.
746 *
747 * Returns:
748 * always returns 0
749 *
750 * Notes: The primary purpose of the PTI tty port 0 is to hook
751 * the syslog daemon to it; thus this port will be open for a
752 * very long time.
753 */
754static int pti_port_activate(struct tty_port *port, struct tty_struct *tty)
755{
756 if (port->tty->index == PTITTY_MINOR_START)
757 console_start(&pti_console);
758 return 0;
759}
760
761/**
762 * pti_port_shutdown()- Used to stop/shutdown any items upon the
763 * last tty port close.
764 *
765 * @port- The tty port number of the PTI device.
766 *
767 * Notes: The primary purpose of the PTI tty port 0 is to hook
768 * the syslog daemon to it; thus this port will be open for a
769 * very long time.
770 */
771static void pti_port_shutdown(struct tty_port *port)
772{
773 if (port->tty->index == PTITTY_MINOR_START)
774 console_stop(&pti_console);
775}
776
777static const struct tty_port_operations tty_port_ops = {
778 .activate = pti_port_activate,
779 .shutdown = pti_port_shutdown,
780};
781
782/*
783 * Note the _probe() call sets everything up and ties the char and tty
784 * to successfully detecting the PTI device on the pci bus.
785 */
786
787/**
788 * pti_pci_probe()- Used to detect pti on the pci bus and set
789 * things up in the driver.
790 *
791 * @pdev- pci_dev struct values for pti.
792 * @ent- pci_device_id struct for pti driver.
793 *
794 * Returns:
795 * 0 for success
796 * otherwise, error
797 */
798static int __devinit pti_pci_probe(struct pci_dev *pdev,
799 const struct pci_device_id *ent)
800{
801 int retval = -EINVAL;
802 int pci_bar = 1;
803
804 dev_dbg(&pdev->dev, "%s %s(%d): PTI PCI ID %04x:%04x\n", __FILE__,
805 __func__, __LINE__, pdev->vendor, pdev->device);
806
807 retval = misc_register(&pti_char_driver);
808 if (retval) {
809 pr_err("%s(%d): CHAR registration failed of pti driver\n",
810 __func__, __LINE__);
811 pr_err("%s(%d): Error value returned: %d\n",
812 __func__, __LINE__, retval);
813 return retval;
814 }
815
816 retval = pci_enable_device(pdev);
817 if (retval != 0) {
818 dev_err(&pdev->dev,
819 "%s: pci_enable_device() returned error %d\n",
820 __func__, retval);
821 return retval;
822 }
823
824 drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
825
826 if (drv_data == NULL) {
827 retval = -ENOMEM;
828 dev_err(&pdev->dev,
829 "%s(%d): kmalloc() returned NULL memory.\n",
830 __func__, __LINE__);
831 return retval;
832 }
833 drv_data->pti_addr = pci_resource_start(pdev, pci_bar);
834
835 retval = pci_request_region(pdev, pci_bar, dev_name(&pdev->dev));
836 if (retval != 0) {
837 dev_err(&pdev->dev,
838 "%s(%d): pci_request_region() returned error %d\n",
839 __func__, __LINE__, retval);
840 kfree(drv_data);
841 return retval;
842 }
843 drv_data->aperture_base = drv_data->pti_addr+APERTURE_14;
844 drv_data->pti_ioaddr =
845 ioremap_nocache((u32)drv_data->aperture_base,
846 APERTURE_LEN);
847 if (!drv_data->pti_ioaddr) {
848 pci_release_region(pdev, pci_bar);
849 retval = -ENOMEM;
850 kfree(drv_data);
851 return retval;
852 }
853
854 pci_set_drvdata(pdev, drv_data);
855
856 tty_port_init(&drv_data->port);
857 drv_data->port.ops = &tty_port_ops;
858
859 tty_register_device(pti_tty_driver, 0, &pdev->dev);
860 tty_register_device(pti_tty_driver, 1, &pdev->dev);
861
862 register_console(&pti_console);
863
864 return retval;
865}
866
867static struct pci_driver pti_pci_driver = {
868 .name = PCINAME,
869 .id_table = pci_ids,
870 .probe = pti_pci_probe,
871 .remove = pti_pci_remove,
872};
873
874/**
875 *
876 * pti_init()- Overall entry/init call to the pti driver.
877 * It starts the registration process with the kernel.
878 *
879 * Returns:
880 * int __init, 0 for success
881 * otherwise value is an error
882 *
883 */
884static int __init pti_init(void)
885{
886 int retval = -EINVAL;
887
888 /* First register module as tty device */
889
890 pti_tty_driver = alloc_tty_driver(1);
891 if (pti_tty_driver == NULL) {
892 pr_err("%s(%d): Memory allocation failed for ptiTTY driver\n",
893 __func__, __LINE__);
894 return -ENOMEM;
895 }
896
897 pti_tty_driver->owner = THIS_MODULE;
898 pti_tty_driver->magic = TTY_DRIVER_MAGIC;
899 pti_tty_driver->driver_name = DRIVERNAME;
900 pti_tty_driver->name = TTYNAME;
901 pti_tty_driver->major = 0;
902 pti_tty_driver->minor_start = PTITTY_MINOR_START;
903 pti_tty_driver->minor_num = PTITTY_MINOR_NUM;
904 pti_tty_driver->num = PTITTY_MINOR_NUM;
905 pti_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
906 pti_tty_driver->subtype = SYSTEM_TYPE_SYSCONS;
907 pti_tty_driver->flags = TTY_DRIVER_REAL_RAW |
908 TTY_DRIVER_DYNAMIC_DEV;
909 pti_tty_driver->init_termios = tty_std_termios;
910
911 tty_set_operations(pti_tty_driver, &pti_tty_driver_ops);
912
913 retval = tty_register_driver(pti_tty_driver);
914 if (retval) {
915 pr_err("%s(%d): TTY registration failed of pti driver\n",
916 __func__, __LINE__);
917 pr_err("%s(%d): Error value returned: %d\n",
918 __func__, __LINE__, retval);
919
920 pti_tty_driver = NULL;
921 return retval;
922 }
923
924 retval = pci_register_driver(&pti_pci_driver);
925
926 if (retval) {
927 pr_err("%s(%d): PCI registration failed of pti driver\n",
928 __func__, __LINE__);
929 pr_err("%s(%d): Error value returned: %d\n",
930 __func__, __LINE__, retval);
931
932 tty_unregister_driver(pti_tty_driver);
933 pr_err("%s(%d): Unregistering TTY part of pti driver\n",
934 __func__, __LINE__);
935 pti_tty_driver = NULL;
936 return retval;
937 }
938
939 return retval;
940}
941
942/**
943 * pti_exit()- Unregisters this module as a tty and pci driver.
944 */
945static void __exit pti_exit(void)
946{
947 int retval;
948
949 tty_unregister_device(pti_tty_driver, 0);
950 tty_unregister_device(pti_tty_driver, 1);
951
952 retval = tty_unregister_driver(pti_tty_driver);
953 if (retval) {
954 pr_err("%s(%d): TTY unregistration failed of pti driver\n",
955 __func__, __LINE__);
956 pr_err("%s(%d): Error value returned: %d\n",
957 __func__, __LINE__, retval);
958 }
959
960 pci_unregister_driver(&pti_pci_driver);
961
962 retval = misc_deregister(&pti_char_driver);
963 if (retval) {
964 pr_err("%s(%d): CHAR unregistration failed of pti driver\n",
965 __func__, __LINE__);
966 pr_err("%s(%d): Error value returned: %d\n",
967 __func__, __LINE__, retval);
968 }
969
970 unregister_console(&pti_console);
971 return;
972}
973
974module_init(pti_init);
975module_exit(pti_exit);
976
977MODULE_LICENSE("GPL");
978MODULE_AUTHOR("Ken Mills, Jay Freyensee");
979MODULE_DESCRIPTION("PTI Driver");
980