diff options
Diffstat (limited to 'packages/linux/linux-turbostation/002_qnap-pic.diff')
-rw-r--r-- | packages/linux/linux-turbostation/002_qnap-pic.diff | 407 |
1 files changed, 407 insertions, 0 deletions
diff --git a/packages/linux/linux-turbostation/002_qnap-pic.diff b/packages/linux/linux-turbostation/002_qnap-pic.diff new file mode 100644 index 0000000000..ce7324088a --- /dev/null +++ b/packages/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 */ |