From 49a3beac398bd3e89dc4c8a5caff106cbd1e0cff Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 21 Feb 2001 13:30:36 +0000 Subject: ITE 8172 patches from Pete Popov slightly hacked by me. --- drivers/char/Makefile | 8 + drivers/char/qtronix.c | 597 ++++++++++++++++++++++++++++++++++++++++++++ drivers/char/qtronixmap.map | 287 +++++++++++++++++++++ drivers/ide/Config.in | 5 + drivers/ide/Makefile | 1 + drivers/ide/ide-pci.c | 16 ++ drivers/ide/it8172.c | 283 +++++++++++++++++++++ 7 files changed, 1197 insertions(+) create mode 100644 drivers/char/qtronix.c create mode 100644 drivers/char/qtronixmap.map create mode 100644 drivers/ide/it8172.c (limited to 'drivers') diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 568c3fb8a..e0fd5b5f5 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -91,6 +91,10 @@ ifneq ($(CONFIG_SUN_SERIAL),) SERIAL = endif +ifeq ($(CONFIG_QTRONIX_KEYBOARD),y) + KEYBD = qtronix.o + KEYMAP = qtronixmap.o +endif obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o obj-$(CONFIG_SERIAL) += $(SERIAL) @@ -208,3 +212,7 @@ consolemap_deftbl.o: consolemap_deftbl.c $(TOPDIR)/include/linux/types.h defkeymap.c: defkeymap.map loadkeys --mktable defkeymap.map > defkeymap.c +ifeq ($(CONFIG_QTRONIX_KEYBOARD),y) +qtronixmap.c: qtronixmap.map + loadkeys --mktable qtronixmap.map > qtronixmap.c +endif diff --git a/drivers/char/qtronix.c b/drivers/char/qtronix.c new file mode 100644 index 000000000..c74aabf2b --- /dev/null +++ b/drivers/char/qtronix.c @@ -0,0 +1,597 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Qtronix 990P infrared keyboard driver. + * + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or support@mvista.com + * + * + * The bottom portion of this driver was take from + * pc_keyb.c Please see that file for copyrights. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +/* + * NOTE: + * + * This driver has only been tested with the Consumer IR + * port of the ITE 8172 system controller. + * + * You do not need this driver if you are using the ps/2 or + * USB adapter that the keyboard ships with. You only need + * this driver if your board has a IR port and the keyboard + * data is being sent directly to the IR. In that case, + * you also need some low-level IR support. See it8172_cir.c. + * + */ + +#ifdef CONFIG_QTRONIX_KEYBOARD + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define leading1 0 +#define leading2 0xF + +#define KBD_CIR_PORT 0 +#define AUX_RECONNECT 170 /* scancode when ps2 device is plugged (back) in */ + +static int data_index; +struct cir_port *cir; +static unsigned char kbdbytes[5]; +static unsigned char cir_data[32]; /* we only need 16 chars */ + +static void kbd_int_handler(int irq, void *dev_id, struct pt_regs *regs); +static int handle_data(unsigned char *p_data); +static inline void handle_mouse_event(unsigned char scancode); +static inline void handle_keyboard_event(unsigned char scancode, int down); +static int __init psaux_init(void); + +static struct aux_queue *queue; /* Mouse data buffer. */ +static int aux_count = 0; + +/* + * Keys accessed through the 'Fn' key + * The Fn key does not produce a key-up sequence. So, the first + * time the user presses it, it will be key-down event. The key + * stays down until the user presses it again. + */ +#define NUM_FN_KEYS 56 +static unsigned char fn_keys[NUM_FN_KEYS] = { + 0,0,0,0,0,0,0,0, /* 0 7 */ + 8,9,10,93,0,0,0,0, /* 8 15 */ + 0,0,0,0,0,0,0,5, /* 16 23 */ + 6,7,91,0,0,0,0,0, /* 24 31 */ + 0,0,0,0,0,2,3,4, /* 32 39 */ + 92,0,0,0,0,0,0,0, /* 40 47 */ + 0,0,0,0,11,0,94,95 /* 48 55 */ + +}; + +void init_qtronix_990P_kbd(void) +{ + int retval; + + cir = (struct cir_port *)kmalloc(sizeof(struct cir_port), GFP_KERNEL); + if (!cir) { + printk("Unable to initialize Qtronix keyboard\n"); + return; + } + + /* + * revisit + * this should be programmable, somehow by the, by the user. + */ + cir->port = KBD_CIR_PORT; + cir->baud_rate = 0x1d; + cir->rdwos = 0; + cir->rxdcr = 0x3; + cir->hcfs = 0; + cir->fifo_tl = 0; + cir->cfq = 0x1d; + cir_port_init(cir); + + retval = request_irq(IT8172_CIR0_IRQ, kbd_int_handler, + (unsigned long )(SA_INTERRUPT|SA_SHIRQ), + (const char *)"Qtronix IR Keyboard", (void *)cir); + + if (retval) { + printk("unable to allocate cir %d irq %d\n", + cir->port, IT8172_CIR0_IRQ); + } +#ifdef CONFIG_PSMOUSE + psaux_init(); +#endif +} + +static inline unsigned char BitReverse(unsigned short key) +{ + unsigned char rkey = 0; + rkey |= (key & 0x1) << 7; + rkey |= (key & 0x2) << 5; + rkey |= (key & 0x4) << 3; + rkey |= (key & 0x8) << 1; + rkey |= (key & 0x10) >> 1; + rkey |= (key & 0x20) >> 3; + rkey |= (key & 0x40) >> 5; + rkey |= (key & 0x80) >> 7; + return rkey; + +} + + +static inline u_int8_t UpperByte(u_int8_t data) +{ + return (data >> 4); +} + + +static inline u_int8_t LowerByte(u_int8_t data) +{ + return (data & 0xF); +} + + +int CheckSumOk(u_int8_t byte1, u_int8_t byte2, + u_int8_t byte3, u_int8_t byte4, u_int8_t byte5) +{ + u_int8_t CheckSum; + + CheckSum = (byte1 & 0x0F) + byte2 + byte3 + byte4 + byte5; + if ( LowerByte(UpperByte(CheckSum) + LowerByte(CheckSum)) != UpperByte(byte1) ) + return 0; + else + return 1; +} + + +static void kbd_int_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + struct cir_port *cir; + int j; + unsigned char int_status; + + cir = (struct cir_port *)dev_id; + int_status = get_int_status(cir);; + if (int_status & 0x4) { + clear_fifo(cir); + return; + } + + while (cir_get_rx_count(cir)) { + + cir_data[data_index] = cir_read_data(cir); + + if (data_index == 0) {/* expecting first byte */ + if (cir_data[data_index] != leading1) { + //printk("!leading byte %x\n", cir_data[data_index]); + set_rx_active(cir); + clear_fifo(cir); + continue; + } + } + if (data_index == 1) { + if ((cir_data[data_index] & 0xf) != leading2) { + set_rx_active(cir); + data_index = 0; /* start over */ + clear_fifo(cir); + continue; + } + } + + if ( (cir_data[data_index] == 0xff)) { /* last byte */ + //printk("data_index %d\n", data_index); + set_rx_active(cir); +#if 0 + for (j=0; j<=data_index; j++) { + printk("rx_data %d: %x\n", j, cir_data[j]); + } +#endif + data_index = 0; + handle_data(cir_data); + return; + } + else if (data_index>16) { + set_rx_active(cir); +#if 0 + printk("warning: data_index %d\n", data_index); + for (j=0; j<=data_index; j++) { + printk("rx_data %d: %x\n", j, cir_data[j]); + } +#endif + data_index = 0; + clear_fifo(cir); + return; + } + data_index++; + } +} + + +#define NUM_KBD_BYTES 5 +static int handle_data(unsigned char *p_data) +{ + u_int32_t bit_bucket; + u_int32_t i, j; + u_int32_t got_bits, next_byte; + int down = 0; + + /* Reorganize the bit stream */ + for (i=0; i<16; i++) + p_data[i] = BitReverse(~p_data[i]); + + /* + * We've already previously checked that p_data[0] + * is equal to leading1 and that (p_data[1] & 0xf) + * is equal to leading2. These twelve bits are the + * leader code. We can now throw them away (the 12 + * bits) and continue parsing the stream. + */ + bit_bucket = p_data[1] << 12; + got_bits = 4; + next_byte = 2; + + /* + * Process four bits at a time + */ + for (i=0; i> 1); + got_bits -= 4; + bit_bucket = bit_bucket << 4; + } + else if ((bit_bucket & 0xC000) == 0x8000) { + /* Convert 10b to 0 */ + kbdbytes[i] = kbdbytes[i] >> 1; + got_bits -= 2; + bit_bucket = bit_bucket << 2; + } + else { + /* bad serial stream */ + return 1; + } + + if (next_byte > 16) { + //printk("error: too many bytes\n"); + return 1; + } + } + } + + + if (!CheckSumOk(kbdbytes[0], kbdbytes[1], + kbdbytes[2], kbdbytes[3], kbdbytes[4])) { + //printk("checksum failed\n"); + return 1; + } + + if (kbdbytes[1] & 0x08) { + //printk("m: %x %x %x\n", kbdbytes[1], kbdbytes[2], kbdbytes[3]); + handle_mouse_event(kbdbytes[1]); + handle_mouse_event(kbdbytes[2]); + handle_mouse_event(kbdbytes[3]); + } + else { + if (kbdbytes[2] == 0) down = 1; +#if 0 + if (down) + printk("down %d\n", kbdbytes[3]); + else + printk("up %d\n", kbdbytes[3]); +#endif + handle_keyboard_event(kbdbytes[3], down); + } + return 0; +} + + +spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED; +static unsigned char handle_kbd_event(void); + + +int pckbd_setkeycode(unsigned int scancode, unsigned int keycode) +{ + printk("pckbd_setkeycode scancode %x keycode %x\n", scancode, keycode); + return 0; +} + +int pckbd_getkeycode(unsigned int scancode) +{ + return scancode; +} + + +int pckbd_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode) +{ + static int prev_scancode = 0; + + if (scancode == 0x00 || scancode == 0xff) { + prev_scancode = 0; + return 0; + } + + /* todo */ + if (!prev_scancode && scancode == 160) { /* Fn key down */ + //printk("Fn key down\n"); + prev_scancode = 160; + return 0; + } + else if (prev_scancode && scancode == 160) { /* Fn key up */ + //printk("Fn key up\n"); + prev_scancode = 0; + return 0; + } + + /* todo */ + if (prev_scancode == 160) { + if (scancode <= NUM_FN_KEYS) { + *keycode = fn_keys[scancode]; + //printk("fn keycode %d\n", *keycode); + } + else + return 0; + } + else if (scancode <= 127) { + *keycode = scancode; + } + else + return 0; + + + return 1; +} + +char pckbd_unexpected_up(unsigned char keycode) +{ + //printk("pckbd_unexpected_up\n"); + return 0; +} + +static unsigned char kbd_exists = 1; + +static inline void handle_keyboard_event(unsigned char scancode, int down) +{ + kbd_exists = 1; + handle_scancode(scancode, down); + tasklet_schedule(&keyboard_tasklet); +} + + +void pckbd_leds(unsigned char leds) +{ +} + +/* dummy */ +void pckbd_init_hw(void) +{ +} + + + +static inline void handle_mouse_event(unsigned char scancode) +{ + if(scancode == AUX_RECONNECT){ + queue->head = queue->tail = 0; /* Flush input queue */ + // __aux_write_ack(AUX_ENABLE_DEV); /* ping the mouse :) */ + return; + } + + add_mouse_randomness(scancode); + if (aux_count) { + int head = queue->head; + + queue->buf[head] = scancode; + head = (head + 1) & (AUX_BUF_SIZE-1); + if (head != queue->tail) { + queue->head = head; + kill_fasync(&queue->fasync, SIGIO, POLL_IN); + wake_up_interruptible(&queue->proc_list); + } + } +} + +static unsigned char get_from_queue(void) +{ + unsigned char result; + unsigned long flags; + + spin_lock_irqsave(&kbd_controller_lock, flags); + result = queue->buf[queue->tail]; + queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1); + spin_unlock_irqrestore(&kbd_controller_lock, flags); + return result; +} + + +static inline int queue_empty(void) +{ + return queue->head == queue->tail; +} + +static int fasync_aux(int fd, struct file *filp, int on) +{ + int retval; + + //printk("fasync_aux\n"); + retval = fasync_helper(fd, filp, on, &queue->fasync); + if (retval < 0) + return retval; + return 0; +} + + +/* + * Random magic cookie for the aux device + */ +#define AUX_DEV ((void *)queue) + +static int release_aux(struct inode * inode, struct file * file) +{ + lock_kernel(); + fasync_aux(-1, file, 0); + aux_count--; + unlock_kernel(); + return 0; +} + +static int open_aux(struct inode * inode, struct file * file) +{ + if (aux_count++) { + return 0; + } + queue->head = queue->tail = 0; /* Flush input queue */ + return 0; +} + +/* + * Put bytes from input queue to buffer. + */ + +static ssize_t read_aux(struct file * file, char * buffer, + size_t count, loff_t *ppos) +{ + DECLARE_WAITQUEUE(wait, current); + ssize_t i = count; + unsigned char c; + + if (queue_empty()) { + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + add_wait_queue(&queue->proc_list, &wait); +repeat: + set_current_state(TASK_INTERRUPTIBLE); + if (queue_empty() && !signal_pending(current)) { + schedule(); + goto repeat; + } + current->state = TASK_RUNNING; + remove_wait_queue(&queue->proc_list, &wait); + } + while (i > 0 && !queue_empty()) { + c = get_from_queue(); + put_user(c, buffer++); + i--; + } + if (count-i) { + file->f_dentry->d_inode->i_atime = CURRENT_TIME; + return count-i; + } + if (signal_pending(current)) + return -ERESTARTSYS; + return 0; +} + +/* + * Write to the aux device. + */ + +static ssize_t write_aux(struct file * file, const char * buffer, + size_t count, loff_t *ppos) +{ + /* + * The ITE boards this was tested on did not have the + * transmit wires connected. + */ + return count; +} + +static unsigned int aux_poll(struct file *file, poll_table * wait) +{ + poll_wait(file, &queue->proc_list, wait); + if (!queue_empty()) + return POLLIN | POLLRDNORM; + return 0; +} + +struct file_operations psaux_fops = { + read: read_aux, + write: write_aux, + poll: aux_poll, + open: open_aux, + release: release_aux, + fasync: fasync_aux, +}; + +/* + * Initialize driver. + */ +static struct miscdevice psaux_mouse = { + PSMOUSE_MINOR, "psaux", &psaux_fops +}; + +static int __init psaux_init(void) +{ + misc_register(&psaux_mouse); + queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL); + memset(queue, 0, sizeof(*queue)); + queue->head = queue->tail = 0; + init_waitqueue_head(&queue->proc_list); + + return 0; +} +#endif diff --git a/drivers/char/qtronixmap.map b/drivers/char/qtronixmap.map new file mode 100644 index 000000000..8d1ff5c1e --- /dev/null +++ b/drivers/char/qtronixmap.map @@ -0,0 +1,287 @@ +# Default kernel keymap. This uses 7 modifier combinations. +keymaps 0-2,4-5,8,12 +# Change the above line into +# keymaps 0-2,4-6,8,12 +# in case you want the entries +# altgr control keycode 83 = Boot +# altgr control keycode 111 = Boot +# below. +# +# In fact AltGr is used very little, and one more keymap can +# be saved by mapping AltGr to Alt (and adapting a few entries): +# keycode 100 = Alt +# +keycode 1 = grave asciitilde + alt keycode 1 = Meta_Escape +keycode 2 = one exclam + alt keycode 2 = Meta_one +keycode 3 = two at at + control keycode 3 = nul + shift control keycode 3 = nul + alt keycode 3 = Meta_two +keycode 4 = three numbersign + control keycode 4 = Escape + alt keycode 4 = Meta_three +keycode 5 = four dollar dollar + control keycode 5 = Control_backslash + alt keycode 5 = Meta_four +keycode 6 = five percent + control keycode 6 = Control_bracketright + alt keycode 6 = Meta_five +keycode 7 = six asciicircum + control keycode 7 = Control_asciicircum + alt keycode 7 = Meta_six +keycode 8 = seven ampersand braceleft + control keycode 8 = Control_underscore + alt keycode 8 = Meta_seven +keycode 9 = eight asterisk bracketleft + control keycode 9 = Delete + alt keycode 9 = Meta_eight +keycode 10 = nine parenleft bracketright + alt keycode 10 = Meta_nine +keycode 11 = zero parenright braceright + alt keycode 11 = Meta_zero +keycode 12 = minus underscore backslash + control keycode 12 = Control_underscore + shift control keycode 12 = Control_underscore + alt keycode 12 = Meta_minus +keycode 13 = equal plus + alt keycode 13 = Meta_equal +keycode 15 = Delete Delete + control keycode 15 = BackSpace + alt keycode 15 = Meta_Delete +keycode 16 = Tab Tab + alt keycode 16 = Meta_Tab +keycode 17 = q +keycode 18 = w +keycode 19 = e +keycode 20 = r +keycode 21 = t +keycode 22 = y +keycode 23 = u +keycode 24 = i +keycode 25 = o +keycode 26 = p +keycode 27 = bracketleft braceleft + control keycode 27 = Escape + alt keycode 27 = Meta_bracketleft +keycode 28 = bracketright braceright + control keycode 28 = Control_bracketright + alt keycode 28 = Meta_bracketright +keycode 29 = backslash bar + control keycode 29 = Control_backslash + alt keycode 29 = Meta_backslash +keycode 30 = Caps_Lock +keycode 31 = a +keycode 32 = s +keycode 33 = d +keycode 34 = f +keycode 35 = g +keycode 36 = h +keycode 37 = j +keycode 38 = k +keycode 39 = l +keycode 40 = semicolon colon + alt keycode 39 = Meta_semicolon +keycode 41 = apostrophe quotedbl + control keycode 40 = Control_g + alt keycode 40 = Meta_apostrophe +keycode 42 = grave asciitilde + control keycode 41 = nul + alt keycode 41 = Meta_grave +keycode 43 = Return + alt keycode 43 = Meta_Control_m +keycode 44 = Shift +keycode 46 = z +keycode 47 = x +keycode 48 = c +keycode 49 = v +keycode 50 = b +keycode 51 = n +keycode 52 = m +keycode 53 = comma less + alt keycode 51 = Meta_comma +keycode 54 = period greater + control keycode 52 = Compose + alt keycode 52 = Meta_period +keycode 55 = slash question + control keycode 53 = Delete + alt keycode 53 = Meta_slash +keycode 57 = Shift +keycode 58 = Control +keycode 60 = Alt +keycode 61 = space space + control keycode 61 = nul + alt keycode 61 = Meta_space +keycode 62 = Alt + +keycode 75 = Insert +keycode 76 = Delete + +keycode 83 = Up +keycode 84 = Down + +keycode 85 = Prior + shift keycode 85 = Scroll_Backward +keycode 86 = Next + shift keycode 86 = Scroll_Forward +keycode 89 = Right + alt keycode 89 = Incr_Console +keycode 79 = Left + alt keycode 79 = Decr_Console + +keycode 90 = Num_Lock + shift keycode 90 = Bare_Num_Lock + +keycode 91 = minus +keycode 92 = plus +keycode 93 = KP_Multiply +keycode 94 = period +keycode 95 = KP_Divide + +keycode 107 = Select +keycode 108 = Down + +keycode 110 = Escape Escape + alt keycode 1 = Meta_Escape + +keycode 112 = F1 F11 Console_13 + control keycode 112 = F1 + alt keycode 112 = Console_1 + control alt keycode 112 = Console_1 +keycode 113 = F2 F12 Console_14 + control keycode 113 = F2 + alt keycode 113 = Console_2 + control alt keycode 113 = Console_2 +keycode 114 = F3 F13 Console_15 + control keycode 114 = F3 + alt keycode 114 = Console_3 + control alt keycode 114 = Console_3 +keycode 115 = F4 F14 Console_16 + control keycode 115 = F4 + alt keycode 115 = Console_4 + control alt keycode 115 = Console_4 +keycode 116 = F5 F15 Console_17 + control keycode 116 = F5 + alt keycode 116 = Console_5 + control alt keycode 116 = Console_5 +keycode 117 = F6 F16 Console_18 + control keycode 117 = F6 + alt keycode 117 = Console_6 + control alt keycode 117 = Console_6 +keycode 118 = F7 F17 Console_19 + control keycode 118 = F7 + alt keycode 118 = Console_7 + control alt keycode 118 = Console_7 +keycode 119 = F8 F18 Console_20 + control keycode 119 = F8 + alt keycode 119 = Console_8 + control alt keycode 119 = Console_8 +keycode 120 = F9 F19 Console_21 + control keycode 120 = F9 + alt keycode 120 = Console_9 + control alt keycode 120 = Console_9 +keycode 121 = F10 F20 Console_22 + control keycode 121 = F10 + alt keycode 121 = Console_10 + control alt keycode 121 = Console_10 + +keycode 126 = Pause + + +string F1 = "\033[[A" +string F2 = "\033[[B" +string F3 = "\033[[C" +string F4 = "\033[[D" +string F5 = "\033[[E" +string F6 = "\033[17~" +string F7 = "\033[18~" +string F8 = "\033[19~" +string F9 = "\033[20~" +string F10 = "\033[21~" +string F11 = "\033[23~" +string F12 = "\033[24~" +string F13 = "\033[25~" +string F14 = "\033[26~" +string F15 = "\033[28~" +string F16 = "\033[29~" +string F17 = "\033[31~" +string F18 = "\033[32~" +string F19 = "\033[33~" +string F20 = "\033[34~" +string Find = "\033[1~" +string Insert = "\033[2~" +string Remove = "\033[3~" +string Select = "\033[4~" +string Prior = "\033[5~" +string Next = "\033[6~" +string Macro = "\033[M" +string Pause = "\033[P" +compose '`' 'A' to 'À' +compose '`' 'a' to 'à' +compose '\'' 'A' to 'Á' +compose '\'' 'a' to 'á' +compose '^' 'A' to 'Â' +compose '^' 'a' to 'â' +compose '~' 'A' to 'Ã' +compose '~' 'a' to 'ã' +compose '"' 'A' to 'Ä' +compose '"' 'a' to 'ä' +compose 'O' 'A' to 'Å' +compose 'o' 'a' to 'å' +compose '0' 'A' to 'Å' +compose '0' 'a' to 'å' +compose 'A' 'A' to 'Å' +compose 'a' 'a' to 'å' +compose 'A' 'E' to 'Æ' +compose 'a' 'e' to 'æ' +compose ',' 'C' to 'Ç' +compose ',' 'c' to 'ç' +compose '`' 'E' to 'È' +compose '`' 'e' to 'è' +compose '\'' 'E' to 'É' +compose '\'' 'e' to 'é' +compose '^' 'E' to 'Ê' +compose '^' 'e' to 'ê' +compose '"' 'E' to 'Ë' +compose '"' 'e' to 'ë' +compose '`' 'I' to 'Ì' +compose '`' 'i' to 'ì' +compose '\'' 'I' to 'Í' +compose '\'' 'i' to 'í' +compose '^' 'I' to 'Î' +compose '^' 'i' to 'î' +compose '"' 'I' to 'Ï' +compose '"' 'i' to 'ï' +compose '-' 'D' to 'Ð' +compose '-' 'd' to 'ð' +compose '~' 'N' to 'Ñ' +compose '~' 'n' to 'ñ' +compose '`' 'O' to 'Ò' +compose '`' 'o' to 'ò' +compose '\'' 'O' to 'Ó' +compose '\'' 'o' to 'ó' +compose '^' 'O' to 'Ô' +compose '^' 'o' to 'ô' +compose '~' 'O' to 'Õ' +compose '~' 'o' to 'õ' +compose '"' 'O' to 'Ö' +compose '"' 'o' to 'ö' +compose '/' 'O' to 'Ø' +compose '/' 'o' to 'ø' +compose '`' 'U' to 'Ù' +compose '`' 'u' to 'ù' +compose '\'' 'U' to 'Ú' +compose '\'' 'u' to 'ú' +compose '^' 'U' to 'Û' +compose '^' 'u' to 'û' +compose '"' 'U' to 'Ü' +compose '"' 'u' to 'ü' +compose '\'' 'Y' to 'Ý' +compose '\'' 'y' to 'ý' +compose 'T' 'H' to 'Þ' +compose 't' 'h' to 'þ' +compose 's' 's' to 'ß' +compose '"' 'y' to 'ÿ' +compose 's' 'z' to 'ß' +compose 'i' 'j' to 'ÿ' diff --git a/drivers/ide/Config.in b/drivers/ide/Config.in index a157767f3..a2c0a282c 100644 --- a/drivers/ide/Config.in +++ b/drivers/ide/Config.in @@ -64,6 +64,10 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then dep_mbool ' Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX $CONFIG_BLK_DEV_IDEDMA_PCI dep_mbool ' PIIXn Tuning support' CONFIG_PIIX_TUNING $CONFIG_BLK_DEV_PIIX $CONFIG_IDEDMA_PCI_AUTO fi + if [ "$CONFIG_MIPS_ITE8172" = "y" -o "$CONFIG_MIPS_IVR" = "y" ]; then + dep_mbool ' IT8172 IDE support' CONFIG_BLK_DEV_IT8172 $CONFIG_BLK_DEV_IDEDMA_PCI + dep_mbool ' IT8172 IDE Tuning support' CONFIG_IT8172_TUNING $CONFIG_BLK_DEV_IT8172 $CONFIG_IDEDMA_PCI_AUTO + fi dep_bool ' NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415 $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' OPTi 82C621 chipset enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621 $CONFIG_EXPERIMENTAL dep_bool ' PROMISE PDC20246/PDC20262/PDC20267 support' CONFIG_BLK_DEV_PDC202XX $CONFIG_BLK_DEV_IDEDMA_PCI @@ -159,6 +163,7 @@ if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \ "$CONFIG_BLK_DEV_OSB4" = "y" -o \ "$CONFIG_BLK_DEV_PDC202XX" = "y" -o \ "$CONFIG_BLK_DEV_PIIX" = "y" -o \ + "$CONFIG_BLK_DEV_IT8172" = "y" -o \ "$CONFIG_BLK_DEV_SIS5513" = "y" -o \ "$CONFIG_BLK_DEV_SLC90E66" = "y" -o \ "$CONFIG_BLK_DEV_SL82C105" = "y" -o \ diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index c2d8a5644..05dcb6a65 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd.o obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o +obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o ide-obj-$(CONFIG_BLK_DEV_AEC62XX) += aec62xx.o ide-obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o diff --git a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c index 7ea7a61e5..a2afee031 100644 --- a/drivers/ide/ide-pci.c +++ b/drivers/ide/ide-pci.c @@ -74,6 +74,7 @@ #define DEVID_AMD7409 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409}) #define DEVID_SLC90E66 ((ide_pci_devid_t){PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1}) #define DEVID_OSB4 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE}) +#define DEVID_ITE8172G ((ide_pci_devid_t){PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G}) #define IDE_IGNORE ((void *)-1) @@ -246,6 +247,18 @@ extern void ide_init_piix(ide_hwif_t *); #define INIT_PIIX NULL #endif +#ifdef CONFIG_BLK_DEV_IT8172 +extern unsigned int pci_init_it8172(struct pci_dev *, const char *); +extern unsigned int ata66_it8172(ide_hwif_t *); +extern void ide_init_it8172(ide_hwif_t *); +#define PCI_IT8172 &pci_init_it8172 +#define INIT_IT8172 &ide_init_it8172 +#else +#define PCI_IT8172 NULL +#define ATA66_IT8172 NULL +#define INIT_IT8172 NULL +#endif + #ifdef CONFIG_BLK_DEV_RZ1000 extern void ide_init_rz1000(ide_hwif_t *); #define INIT_RZ1000 &ide_init_rz1000 @@ -381,6 +394,7 @@ static ide_pci_device_t ide_pci_chipsets[] __initdata = { {DEVID_AMD7409, "AMD7409", PCI_AMD7409, ATA66_AMD7409, INIT_AMD7409, DMA_AMD7409, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, {DEVID_SLC90E66,"SLC90E66", PCI_SLC90E66, ATA66_SLC90E66, INIT_SLC90E66, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_OSB4, "ServerWorks OSB4", PCI_OSB4, ATA66_OSB4, INIT_OSB4, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_ITE8172G,"IT8172G", PCI_IT8172, NULL, INIT_IT8172, NULL, {{0x00,0x00,0x00}, {0x40,0x00,0x01}}, ON_BOARD, 0 }, {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; /* @@ -784,6 +798,8 @@ void __init ide_scan_pcidev (struct pci_dev *dev) return; else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) return; /* CY82C693 is more than only a IDE controller */ + else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_ITE8172G) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) + return; /* IT8172G is also more than only an IDE controller */ else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1)) return; /* UM8886A/BF pair */ else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366)) diff --git a/drivers/ide/it8172.c b/drivers/ide/it8172.c new file mode 100644 index 000000000..937d3e6d1 --- /dev/null +++ b/drivers/ide/it8172.c @@ -0,0 +1,283 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * IT8172 IDE controller support + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * stevel@mvista.com or support@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ide_modes.h" + +/* + * Prototypes + */ +static void it8172_tune_drive (ide_drive_t *drive, byte pio); +#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IT8172_TUNING) +static byte it8172_dma_2_pio (byte xfer_rate); +static int it8172_tune_chipset (ide_drive_t *drive, byte speed); +static int it8172_config_drive_for_dma (ide_drive_t *drive); +static int it8172_dmaproc(ide_dma_action_t func, ide_drive_t *drive); +#endif +unsigned int __init pci_init_it8172 (struct pci_dev *dev, const char *name); +void __init ide_init_it8172 (ide_hwif_t *hwif); + + +/* + * Based on settings done by AMI BIOS + * (might be usefull if drive is not registered in CMOS for any reason). + */ +static void it8172_tune_drive (ide_drive_t *drive, byte pio) +{ + unsigned long flags; + u16 master_data; + byte slave_data; + int is_slave = (&HWIF(drive)->drives[1] == drive); + int master_port = HWIF(drive)->index ? 0x42 : 0x40; + int slave_port = 0x44; + /* ISP RTC */ + byte timings[][2] = { { 0, 0 }, + { 0, 0 }, + { 1, 0 }, + { 2, 1 }, + { 2, 3 }, }; + + pio = ide_get_best_pio_mode(drive, pio, 5, NULL); + pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data); + if (is_slave) { + master_data = master_data | 0x4000; + if (pio > 1) + /* enable PPE, IE and TIME */ + master_data = master_data | 0x0070; + pci_read_config_byte(HWIF(drive)->pci_dev, slave_port, &slave_data); + slave_data = slave_data & (HWIF(drive)->index ? 0x0f : 0xf0); + slave_data = slave_data | + ((timings[pio][0] << 2) | (timings[pio][1] + << (HWIF(drive)->index ? 4 : 0))); + } else { + master_data = master_data & 0xccf8; + if (pio > 1) + /* enable PPE, IE and TIME */ + master_data = master_data | 0x0007; + master_data = master_data | (timings[pio][0] << 12) | + (timings[pio][1] << 8); + } + save_flags(flags); + cli(); + pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data); + if (is_slave) + pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data); + restore_flags(flags); +} + +#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IT8172_TUNING) +/* + * + */ +static byte it8172_dma_2_pio (byte xfer_rate) +{ + switch(xfer_rate) { + case XFER_UDMA_5: + case XFER_UDMA_4: + case XFER_UDMA_3: + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + case XFER_MW_DMA_2: + case XFER_PIO_4: + return 4; + case XFER_MW_DMA_1: + case XFER_PIO_3: + return 3; + case XFER_SW_DMA_2: + case XFER_PIO_2: + return 2; + case XFER_MW_DMA_0: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + case XFER_PIO_1: + case XFER_PIO_0: + case XFER_PIO_SLOW: + default: + return 0; + } +} + +static int it8172_tune_chipset (ide_drive_t *drive, byte speed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + int a_speed = 3 << (drive->dn * 4); + int u_flag = 1 << drive->dn; + int u_speed = 0; + int err = 0; + byte reg48, reg4a; + + pci_read_config_byte(dev, 0x48, ®48); + pci_read_config_byte(dev, 0x4a, ®4a); + + switch(speed) { + case XFER_UDMA_4: + case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; + case XFER_UDMA_5: + case XFER_UDMA_3: + case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break; + case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: + case XFER_SW_DMA_2: break; + default: return -1; + } + + if (speed >= XFER_UDMA_0) { + if (!(reg48 & u_flag)) + pci_write_config_byte(dev, 0x48, reg48|u_flag); + if (!(reg4a & u_speed)) { + pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed); + pci_write_config_byte(dev, 0x4a, reg4a|u_speed); + } + } + if (speed < XFER_UDMA_0) { + if (reg48 & u_flag) + pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); + if (reg4a & a_speed) + pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed); + } + + it8172_tune_drive(drive, it8172_dma_2_pio(speed)); + +#if IT8172_DEBUG + printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn); +#endif + if (!drive->init_speed) + drive->init_speed = speed; + err = ide_config_drive_speed(drive, speed); + drive->current_speed = speed; + return err; +} + +static int it8172_config_drive_for_dma (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + byte speed; + + if (id->dma_ultra & 0x0010) { + speed = XFER_UDMA_2; + } else if (id->dma_ultra & 0x0008) { + speed = XFER_UDMA_1; + } else if (id->dma_ultra & 0x0004) { + speed = XFER_UDMA_2; + } else if (id->dma_ultra & 0x0002) { + speed = XFER_UDMA_1; + } else if (id->dma_ultra & 0x0001) { + speed = XFER_UDMA_0; + } else if (id->dma_mword & 0x0004) { + speed = XFER_MW_DMA_2; + } else if (id->dma_mword & 0x0002) { + speed = XFER_MW_DMA_1; + } else if (id->dma_1word & 0x0004) { + speed = XFER_SW_DMA_2; + } else { + speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); + } + + (void) it8172_tune_chipset(drive, speed); + + return ((int)((id->dma_ultra >> 11) & 7) ? ide_dma_on : + ((id->dma_ultra >> 8) & 7) ? ide_dma_on : + ((id->dma_mword >> 8) & 7) ? ide_dma_on : + ((id->dma_1word >> 8) & 7) ? ide_dma_on : + ide_dma_off_quietly); +} + +static int it8172_dmaproc(ide_dma_action_t func, ide_drive_t *drive) +{ + switch (func) { + case ide_dma_check: + return ide_dmaproc((ide_dma_action_t)it8172_config_drive_for_dma(drive), + drive); + default : + break; + } + /* Other cases are done by generic IDE-DMA code. */ + return ide_dmaproc(func, drive); +} +#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_IT8172_TUNING) */ + +unsigned int __init pci_init_it8172 (struct pci_dev *dev, const char *name) +{ + unsigned char progif; + + /* + * Place both IDE interfaces into PCI "native" mode + */ + (void)pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); + (void)pci_write_config_byte(dev, PCI_CLASS_PROG, progif | 0x05); + + return IT8172_IDE_IRQ; +} + + +void __init ide_init_it8172 (ide_hwif_t *hwif) +{ + struct pci_dev* dev = hwif->pci_dev; + unsigned long cmdBase, ctrlBase; + + hwif->tuneproc = &it8172_tune_drive; + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + + if (!hwif->dma_base) + return; + +#ifndef CONFIG_BLK_DEV_IDEDMA + hwif->autodma = 0; +#else /* CONFIG_BLK_DEV_IDEDMA */ +#ifdef CONFIG_IT8172_TUNING + hwif->autodma = 1; + hwif->dmaproc = &it8172_dmaproc; + hwif->speedproc = &it8172_tune_chipset; +#endif /* CONFIG_IT8172_TUNING */ +#endif /* !CONFIG_BLK_DEV_IDEDMA */ + + cmdBase = dev->resource[0].start; + ctrlBase = dev->resource[1].start; + + ide_init_hwif_ports(&hwif->hw, cmdBase, ctrlBase | 2, NULL); + memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); + hwif->noprobe = 0; +} -- cgit v1.2.3