aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-turbostation/002_qnap-pic.diff
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-turbostation/002_qnap-pic.diff')
-rw-r--r--recipes/linux/linux-turbostation/002_qnap-pic.diff407
1 files changed, 407 insertions, 0 deletions
diff --git a/recipes/linux/linux-turbostation/002_qnap-pic.diff b/recipes/linux/linux-turbostation/002_qnap-pic.diff
new file mode 100644
index 0000000000..ce7324088a
--- /dev/null
+++ b/recipes/linux/linux-turbostation/002_qnap-pic.diff
@@ -0,0 +1,407 @@
+Index: linux-2.6.19/arch/ppc/platforms/qnap_pic.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.19/arch/ppc/platforms/qnap_pic.c 2007-02-25 06:06:59.000000000 +0100
+@@ -0,0 +1,286 @@
++#include <linux/module.h>
++#include <linux/poll.h>
++#include <linux/miscdevice.h>
++#include <linux/serial_core.h>
++#include <linux/serial_reg.h>
++#include <asm/serial.h>
++#include <asm/io.h>
++
++#include "qnap_pic.h"
++#include "qnap_pic_user.h"
++
++static wait_queue_head_t pic_wait;
++static wait_queue_head_t queue_empty_wait;
++static int use_int = 0;
++static int tx_begin = 0, tx_end = 0, rx_begin = 0, rx_end = 0;
++static unsigned char *tx_buf = NULL;
++static unsigned char rx_buf[QUEUE_BUFSIZE];
++static int usage = 0;
++int usb_button_enabled = 1;
++
++static struct qnap_pic_event pic_event[QNAP_PIC_TOTAL_EVENT];
++
++static unsigned char qnap_pic_inb(unsigned long addr)
++{
++ return readb((void __iomem *)addr);
++}
++
++static void qnap_pic_outb(unsigned long addr, unsigned char val)
++{
++ writeb(val, (void __iomem *)addr);
++}
++
++static irqreturn_t qnap_pic_isr(int irq, void *dev_id, struct pt_regs *regs)
++{
++ unsigned char int_id;
++ unsigned char data;
++ int i, need_wakeup;
++
++ need_wakeup = 0;
++ for (i = 0 ; i < 10 ; i++) {
++ int_id = (qnap_pic_inb(SANDPOINT_SERIAL_1 + UART_IIR) & 0x0f);
++ if (int_id & 0x01)
++ break;
++ int_id >>= 1;
++ switch (int_id) {
++ case 3:
++ qnap_pic_inb(SANDPOINT_SERIAL_1 + UART_LSR);
++ break;
++
++ case 2:
++ case 6:
++ while (qnap_pic_inb(SANDPOINT_SERIAL_1 + UART_LSR) & UART_LSR_DR) {
++ data = qnap_pic_inb(SANDPOINT_SERIAL_1 + UART_RX);
++ if((data == 0x72) ||
++ (data == QNAP_PIC_USB_COPY_BUTTON && !usb_button_enabled))
++ continue; // Skip it
++
++ if (((rx_end + 1) % QUEUE_BUFSIZE) != rx_begin) {
++ rx_buf[rx_end] = data;
++ //printk("qnap pic: get byte 0x%x\n", rx_buf[rx_end]);
++ rx_end = ((rx_end + 1) % QUEUE_BUFSIZE);
++ }
++ need_wakeup = 1;
++ }
++ //need_wakeup = 1;
++ break;
++ }
++ }
++ if (i == 10)
++ printk("qnap pic: Reach maximal count of pending interrupts.\n");
++ if (need_wakeup)
++ wake_up_interruptible(&pic_wait);
++ return IRQ_HANDLED;
++}
++
++int send_message_to_app(unsigned char message)
++{
++ if (((rx_end + 1) % QUEUE_BUFSIZE) != rx_begin) {
++ rx_buf[rx_end] = message;
++ //printk("qnap pic: get byte 0x%x\n", rx_buf[rx_end]);
++ rx_end = ((rx_end + 1) % QUEUE_BUFSIZE);
++ }
++
++ wake_up_interruptible(&pic_wait);
++
++ return 0;
++}
++
++void __init qnap_pic_init(void)
++{
++ unsigned char dcr;
++
++ /* enable UART2 */
++ dcr = qnap_pic_inb(SANDPOINT_SERIAL_1 + UART_DCR);
++ dcr |= 0x01;
++ qnap_pic_outb(SANDPOINT_SERIAL_1 + UART_DCR, dcr);
++ /* Access baud rate */
++ qnap_pic_outb(SANDPOINT_SERIAL_1 + UART_LCR, UART_LCR_DLAB);
++ /* Input clock. */
++#ifdef CONFIG_QNAP_UART_CLK_100
++ qnap_pic_outb(SANDPOINT_SERIAL_1 + UART_DLL, (325/*(BASE_BAUD / SERIAL_BAUD)*/ & 0xFF));
++ qnap_pic_outb(SANDPOINT_SERIAL_1 + UART_DLM, (325/*(BASE_BAUD / SERIAL_BAUD)*/ >> 8));
++#else
++ qnap_pic_outb(SANDPOINT_SERIAL_1 + UART_DLL, (435/*(BASE_BAUD / SERIAL_BAUD)*/ & 0xFF));
++ qnap_pic_outb(SANDPOINT_SERIAL_1 + UART_DLM, (435/*(BASE_BAUD / SERIAL_BAUD)*/ >> 8));
++#endif
++ /* 8 data, 1 stop, no parity */
++ qnap_pic_outb(SANDPOINT_SERIAL_1 + UART_LCR, 0x03);
++}
++
++static int pic_open(struct inode *inode, struct file *fp)
++{
++ int result;
++
++ if (usage == 0) {
++ if ((result = request_irq(SANDPOINT_SERIAL_1_INT, qnap_pic_isr, SA_INTERRUPT, "qnap-pic", NULL)) < 0) {
++ printk("qnap pic - failed to attach interrupt\n");
++ return result;
++ }
++ tx_buf = (unsigned char*)kmalloc(QUEUE_BUFSIZE, GFP_KERNEL);
++ if (tx_buf == NULL) {
++ free_irq(SANDPOINT_SERIAL_1_INT, NULL);
++ return -ENOMEM;
++ }
++ use_int = 1;
++ qnap_pic_outb(SANDPOINT_SERIAL_1 + UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR | UART_FCR_TRIGGER_14);
++ qnap_pic_outb(SANDPOINT_SERIAL_1 + UART_IER, UART_IER_RDI);
++ }
++ usage++;
++ return 0;
++}
++
++static int pic_release(struct inode *inode, struct file *fp)
++{
++ usage--;
++ if (usage == 0) {
++ while (tx_begin != tx_end)
++ interruptible_sleep_on(&queue_empty_wait);
++ qnap_pic_outb(SANDPOINT_SERIAL_1 + UART_IER, 0);
++ qnap_pic_outb(SANDPOINT_SERIAL_1 + UART_FCR, 0);
++ free_irq(SANDPOINT_SERIAL_1_INT, NULL);
++ use_int = 0;
++ if (tx_buf)
++ kfree(tx_buf);
++ }
++ return 0;
++}
++
++static int pic_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
++{
++ int i, bytes;
++ spinlock_t lock = SPIN_LOCK_UNLOCKED;
++ unsigned long flags;
++ struct qnap_pic_ioctl qpi;
++
++ switch (cmd) {
++ case IOCTL_MSG_GET_MESSAGE:
++ memset(&qpi, 0, sizeof(struct qnap_pic_ioctl));
++ while (rx_begin == rx_end) {
++ //printk("PIC without any event\n");
++ interruptible_sleep_on(&pic_wait);
++ if (signal_pending(current))
++ {
++ printk("pic_ioctl: signal_pending current failed\n");
++ return -ERESTARTSYS;
++ }
++ }
++ spin_lock_irqsave(lock, flags);
++ // calculate how many bytes available
++ bytes = ((rx_end + QUEUE_BUFSIZE) - rx_begin) % QUEUE_BUFSIZE;
++ // read data as many as possible
++ for (i = 0 ; i < bytes ; i++) {
++ qpi.pic_data[i] = rx_buf[rx_begin];
++ qpi.count++;
++ rx_begin = (rx_begin + 1) % QUEUE_BUFSIZE;
++ }
++ spin_unlock_irqrestore(lock, flags);
++ return copy_to_user((void *)arg, &qpi, sizeof(struct qnap_pic_ioctl));
++
++ case IOCTL_MSG_SEND_MESSAGE:
++ memset(&qpi, 0, sizeof(struct qnap_pic_ioctl));
++ if (copy_from_user(&qpi, (struct qnap_pic_ioctl *)arg, sizeof(struct qnap_pic_ioctl)))
++ break;
++ for (i = 0; i < QUEUE_BUFSIZE && i < qpi.count; i += 2) {
++ if (qpi.pic_data[i] >= QNAP_PIC_TOTAL_EVENT || qpi.pic_data[i + 1] >= PIC_EVENT_COMMAND_TYPE)
++ continue;
++ switch(qpi.pic_data[i]) {
++ case QNAP_PIC_USB_COPY:
++ if(qpi.pic_data[i+1] == QNAP_PIC_EVENT_ON)
++ usb_button_enabled = 0;
++ else
++ usb_button_enabled = 1;
++ break;
++ }
++ qnap_pic_send_command(pic_event[qpi.pic_data[i]].command[qpi.pic_data[i + 1]], pic_event[qpi.pic_data[i]].count[qpi.pic_data[i + 1]]);
++ }
++ return 0;
++ case IOCTL_MSG_SEND_RAW_COMMAND:
++ memset(&qpi, 0, sizeof(struct qnap_pic_ioctl));
++ if (copy_from_user(&qpi, (struct qnap_pic_ioctl *)arg, sizeof(struct qnap_pic_ioctl)))
++ break;
++ qnap_pic_send_command(qpi.pic_data, qpi.count);
++ return 0;
++ }
++ return -EINVAL;
++}
++
++static struct file_operations pic_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = pic_ioctl,
++ .open = pic_open,
++ .release = pic_release,
++};
++
++static struct miscdevice pic_device = {
++ PIC_MINOR, "pic", &pic_fops
++};
++
++static void __init qnap_pic_event_init(void)
++{
++ memset(pic_event, 0, sizeof(pic_event));
++ pic_event[QNAP_PIC_BOOT_COMPLETE].command[QNAP_PIC_EVENT_ON][0] = QNAP_PIC_STATUS_GREEN_ON;
++ pic_event[QNAP_PIC_BOOT_COMPLETE].command[QNAP_PIC_EVENT_ON][1] = QNAP_PIC_BUZZER_LONG;
++ pic_event[QNAP_PIC_BOOT_COMPLETE].count[QNAP_PIC_EVENT_ON] = 2;
++ pic_event[QNAP_PIC_WRONG_HD_FORMAT].command[QNAP_PIC_EVENT_ON][0] = QNAP_PIC_STATUS_RED_ON;
++ pic_event[QNAP_PIC_WRONG_HD_FORMAT].count[QNAP_PIC_EVENT_ON] = 1;
++ pic_event[QNAP_PIC_WRONG_HD_FORMAT].command[QNAP_PIC_EVENT_OFF][0] = QNAP_PIC_STATUS_GREEN_ON;
++ pic_event[QNAP_PIC_WRONG_HD_FORMAT].count[QNAP_PIC_EVENT_OFF] = 1;
++ pic_event[QNAP_PIC_POWER_OFF].command[QNAP_PIC_EVENT_ON][0] = QNAP_PIC_STATUS_OFF;
++ pic_event[QNAP_PIC_POWER_OFF].command[QNAP_PIC_EVENT_ON][1] = QNAP_PIC_POWER_LED_BLINK;
++ pic_event[QNAP_PIC_POWER_OFF].count[QNAP_PIC_EVENT_ON] = 2;
++ pic_event[QNAP_PIC_HD_STANDBY].command[QNAP_PIC_EVENT_ON][0] = QNAP_PIC_STATUS_GREEN_ON;
++ pic_event[QNAP_PIC_HD_STANDBY].command[QNAP_PIC_EVENT_ON][1] = QNAP_PIC_POWER_LED_BLINK;
++ pic_event[QNAP_PIC_HD_STANDBY].count[QNAP_PIC_EVENT_ON] = 2;
++ pic_event[QNAP_PIC_HD_STANDBY].command[QNAP_PIC_EVENT_OFF][0] = QNAP_PIC_STATUS_GREEN_ON;
++ pic_event[QNAP_PIC_HD_STANDBY].command[QNAP_PIC_EVENT_OFF][1] = QNAP_PIC_POWER_LED_ON;
++ pic_event[QNAP_PIC_HD_STANDBY].count[QNAP_PIC_EVENT_OFF] = 2;
++ pic_event[QNAP_PIC_USB_COPY].command[QNAP_PIC_EVENT_ON][0] = QNAP_PIC_USB_LED_BLINK;
++ pic_event[QNAP_PIC_USB_COPY].count[QNAP_PIC_EVENT_ON] = 1;
++ pic_event[QNAP_PIC_USB_COPY].command[QNAP_PIC_EVENT_OFF][0] = QNAP_PIC_USB_LED_OFF;
++ pic_event[QNAP_PIC_USB_COPY].count[QNAP_PIC_EVENT_OFF] = 1;
++ pic_event[QNAP_PIC_SET_DEFAULT].command[QNAP_PIC_EVENT_ON][0] = QNAP_PIC_BUZZER_SHORT;
++ pic_event[QNAP_PIC_SET_DEFAULT].count[QNAP_PIC_EVENT_ON] = 1;
++ pic_event[QNAP_PIC_POWER_RECOVERY].command[QNAP_PIC_EVENT_ON][0] = QNAP_PIC_ENABLE_POWER_RECOVERY;
++ pic_event[QNAP_PIC_POWER_RECOVERY].count[QNAP_PIC_EVENT_ON] = 1;
++ pic_event[QNAP_PIC_POWER_RECOVERY].command[QNAP_PIC_EVENT_OFF][0] = QNAP_PIC_DISABLE_POWER_RECOVERY;
++ pic_event[QNAP_PIC_POWER_RECOVERY].count[QNAP_PIC_EVENT_OFF] = 1;
++}
++
++static __init int qnap_pic_init2(void)
++{
++ int result;
++
++ result = misc_register(&pic_device);
++ if (result < 0)
++ printk("qnap pic: fail to register misc device\n");
++ else {
++ //printk("qnap pic: suceed to register misc device\n");
++ init_waitqueue_head(&pic_wait);
++ init_waitqueue_head(&queue_empty_wait);
++ qnap_pic_event_init();
++ }
++ return result;
++}
++
++__initcall(qnap_pic_init2);
++
++static void qnap_pic_putc(unsigned char c)
++{
++ while ((qnap_pic_inb(SANDPOINT_SERIAL_1 + UART_LSR) & UART_LSR_THRE) == 0)
++ ;
++ qnap_pic_outb(SANDPOINT_SERIAL_1 + UART_TX, c);
++}
++
++int qnap_pic_send_command(char *data, int count)
++{
++ int i;
++
++ if (data == NULL || count <= 0)
++ return -EINVAL;
++ for (i = 0; i < count; i++)
++ qnap_pic_putc(data[i]);
++ return count;
++}
++EXPORT_SYMBOL(qnap_pic_send_command);
++EXPORT_SYMBOL(send_message_to_app);
+--- linux-2.6.16.vanilla/arch/ppc/platforms/qnap_pic.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16/arch/ppc/platforms/qnap_pic.h 2007-02-25 05:09:57.000000000 +0100
+@@ -0,0 +1,19 @@
++#ifndef __PPC_PLATFORMS_QNAP_PIC_H
++#define __PPC_PLATFORMS_QNAP_PIC_H
++
++extern void qnap_pic_init(void);
++extern int qnap_pic_send_command(char *data, int count);
++
++#define UART_DSR 0x10
++#define UART_DCR 0x11
++#define SERIAL_BAUD 19200
++
++#define PIC_EVENT_COMMAND_SIZE 8
++#define PIC_EVENT_COMMAND_TYPE 2
++
++struct qnap_pic_event {
++ unsigned char command[PIC_EVENT_COMMAND_TYPE][PIC_EVENT_COMMAND_SIZE];
++ int count[PIC_EVENT_COMMAND_TYPE];
++};
++
++#endif /* __PPC_PLATFORMS_QNAP_PIC_H */
+--- linux-2.6.16.vanilla/arch/ppc/platforms/qnap_pic_user.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.16/arch/ppc/platforms/qnap_pic_user.h 2007-02-25 05:09:57.000000000 +0100
+@@ -0,0 +1,91 @@
++#ifndef __PPC_PLATFORMS_QNAP_PIC_USER_H
++#define __PPC_PLATFORMS_QNAP_PIC_USER_H
++
++#define QUEUE_BUFSIZE 16
++#define PIC_MINOR 80
++#define PIC_DEV "/dev/pic"
++
++struct qnap_pic_ioctl {
++ unsigned char pic_data[QUEUE_BUFSIZE];
++ int count;
++};
++
++#define IOCTL_MSG_MAGIC 'Q'
++#define IOCTL_MSG_GET_MESSAGE _IOR(IOCTL_MSG_MAGIC, 1000, struct qnap_pic_ioctl)
++#define IOCTL_MSG_SEND_MESSAGE _IOW(IOCTL_MSG_MAGIC, 1001, struct qnap_pic_ioctl)
++#define IOCTL_MSG_SEND_RAW_COMMAND _IOW(IOCTL_MSG_MAGIC, 1002, struct qnap_pic_ioctl)
++
++#define QNAP_PIC_BOOT_COMPLETE 0
++#define QNAP_PIC_NO_HD 1
++#define QNAP_PIC_WRONG_HD_FORMAT 2
++#define QNAP_PIC_HD_BAD_BLOCK 3
++#define QNAP_PIC_HD_FULL 4
++#define QNAP_PIC_FIRMWARE_UPDATE 5
++#define QNAP_PIC_POWER_OFF 6
++#define QNAP_PIC_HD_STANDBY 7
++#define QNAP_PIC_USB_COPY 8
++#define QNAP_PIC_SET_DEFAULT 9
++#define QNAP_PIC_POWER_RECOVERY 10
++
++#define QNAP_PIC_TOTAL_EVENT 11
++#define QNAP_PIC_EVENT_OFF 0
++#define QNAP_PIC_EVENT_ON 1
++
++#define QNAP_PIC_POWER_BUTTON 0x40
++#define QNAP_PIC_USB_COPY_BUTTON 0x68
++#define QNAP_PIC_SET_DEFAULT_BUTTON 0x6A
++#define QNAP_PIC_FAN_ENABLE 0x71
++#define QNAP_PIC_FAN_DISABLE 0x72
++#define QNAP_PIC_FAN_ERROR 0x73
++#define QNAP_PIC_FAN_NORMAL 0x74
++#define QNAP_PIC_POWER_RECOVERY_ON 0x79
++#define QNAP_PIC_POWER_RECOVERY_OFF 0x7A
++#define QNAP_NET_NIC_UP 0x81
++#define QNAP_NET_NIC_DOWN 0x82
++
++/*add by KenChen for GIGA Lan up notification 20060329
++#define GIGA 1000
++#define QNAP_GIGA_LAN_UP 0x7C
++#define QNAP_NOT_GIGA_LAN_UP 0x7D
++end here*/
++
++//Ricky added some hotswap command
++#define QNAP_ESATA_UP 0x83
++#define QNAP_ESATA_DOWN 0x84
++#define QNAP_USB_FRONT_UP 0x85
++#define QNAP_USB_FRONT_DOWN 0x86
++#define QNAP_USB_B_UPPER_UP 0x87
++#define QNAP_USB_B_UPPER_DOWN 0x88
++#define QNAP_USB_B_LOWER_UP 0x89
++#define QNAP_USB_B_LOWER_DOWN 0x8A
++#define QNAP_USB_PRINTER_UP 0x8B
++#define QNAP_USB_PRINTER_DOWN 0x8C
++#define QNAP_SATA_UP 0x8D
++#define QNAP_SATA_DOWN 0x8E
++//End
++
++#define MD_REBUILDING 0x91
++#define MD_REBUILDING_DONE 0x92
++#define MD_REBUILDING_SKIP 0x93
++
++#define QNAP_PIC_SOFTWARE_SHUTDOWN 0x41
++#define QNAP_PIC_POWER_RECOVERY_STATUS 0x46
++#define QNAP_PIC_POWER_LED_OFF 0x4B
++#define QNAP_PIC_POWER_LED_BLINK 0x4C
++#define QNAP_PIC_POWER_LED_ON 0x4D
++#define QNAP_PIC_ENABLE_POWER_RECOVERY 0x48
++#define QNAP_PIC_DISABLE_POWER_RECOVERY 0x49
++#define QNAP_PIC_BUZZER_SHORT 0x50
++#define QNAP_PIC_BUZZER_LONG 0x51
++#define QNAP_PIC_STATUS_RED_BLINK 0x54
++#define QNAP_PIC_STATUS_GREEN_BLINK 0x55
++#define QNAP_PIC_STATUS_GREEN_ON 0x56
++#define QNAP_PIC_STATUS_RED_ON 0x57
++#define QNAP_PIC_STATUS_BOTH_BLINK 0x58
++#define QNAP_PIC_STATUS_OFF 0x59
++#define QNAP_PIC_USB_LED_ON 0x60
++#define QNAP_PIC_USB_LED_BLINK 0x61
++#define QNAP_PIC_USB_LED_OFF 0x62
++#define QNAP_PIC_SOFTWARE_REBOOT 0x66
++
++#endif /* __PPC_PLATFORMS_QNAP_PIC_USER_H */