!C99Shell v. 1.0 pre-release build #13!

Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a 

uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 

uid=99(nobody) gid=98(nobody) groups=98(nobody) 

Safe-mode: OFF (not secure)

/usr/src/linux-2.4.18-xfs-1.1/drivers/sbus/char/   drwxr-xr-x
Free 318.37 GB of 458.09 GB (69.5%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     pcikbd.c (33.03 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* $Id: pcikbd.c,v 1.61 2001/08/18 09:40:46 davem Exp $
 * pcikbd.c: Ultra/AX PC keyboard support.
 *
 * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
 * JavaStation support by Pete A. Zaitcev.
 *
 * This code is mainly put together from various places in
 * drivers/char, please refer to these sources for credits
 * to the original authors.
 */

#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/random.h>
#include <linux/miscdevice.h>
#include <linux/kbd_ll.h>
#include <linux/kbd_kern.h>
#include <linux/vt_kern.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <linux/init.h>

#include <asm/ebus.h>
#if defined(CONFIG_USB) && defined(CONFIG_SPARC64)
#include <asm/isa.h>
#endif
#include <asm/oplib.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/uaccess.h>

/*
 * Different platforms provide different permutations of names.
 * AXi - kb_ps2, kdmouse.
 * MrCoffee - keyboard, mouse.
 * Espresso - keyboard, kdmouse.
 */
#define    PCI_KB_NAME1    "kb_ps2"
#define PCI_KB_NAME2    "keyboard"
#define PCI_MS_NAME1    "kdmouse"
#define PCI_MS_NAME2    "mouse"

#include "pcikbd.h"
#include "sunserial.h"

#ifndef __sparc_v9__
static int pcikbd_mrcoffee = 0;
#else
#define pcikbd_mrcoffee 0
extern void (*prom_keyboard)(void);
#endif

static unsigned long pcikbd_iobase = 0;
static unsigned int pcikbd_irq = 0;

/* used only by send_data - set by keyboard_interrupt */
static volatile unsigned char reply_expected = 0;
static volatile unsigned char acknowledge = 0;
static volatile unsigned char resend = 0;

static spinlock_t pcikbd_lock = SPIN_LOCK_UNLOCKED;

static void pcikbd_write(int address, int data);
static int pcikbd_wait_for_input(void);

unsigned char pckbd_read_mask = KBD_STAT_OBF;

extern int pcikbd_init(void);
extern void pci_compute_shiftstate(void);
extern int pci_setkeycode(unsigned int, unsigned int);
extern int pci_getkeycode(unsigned int);
extern void pci_setledstate(struct kbd_struct *, unsigned int);
extern unsigned char pci_getledstate(void);

#define pcikbd_inb(x)     inb(x)
#define pcikbd_outb(v,x)  outb(v,x)

/* Wait for keyboard controller input buffer to drain.
 * Must be invoked under the pcikbd_lock.
 */
static void kb_wait(void)
{
    unsigned long timeout = 250;

    do {
        if(!(pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG) & KBD_STAT_IBF))
            return;
        mdelay(1);
    } while (--timeout);
}

/*
 * Translation of escaped scancodes to keycodes.
 * This is now user-settable.
 * The keycodes 1-88,96-111,119 are fairly standard, and
 * should probably not be changed - changing might confuse X.
 * X also interprets scancode 0x5d (KEY_Begin).
 *
 * For 1-88 keycode equals scancode.
 */

#define E0_KPENTER 96
#define E0_RCTRL   97
#define E0_KPSLASH 98
#define E0_PRSCR   99
#define E0_RALT    100
#define E0_BREAK   101  /* (control-pause) */
#define E0_HOME    102
#define E0_UP      103
#define E0_PGUP    104
#define E0_LEFT    105
#define E0_RIGHT   106
#define E0_END     107
#define E0_DOWN    108
#define E0_PGDN    109
#define E0_INS     110
#define E0_DEL     111

#define E1_PAUSE   119

/*
 * The keycodes below are randomly located in 89-95,112-118,120-127.
 * They could be thrown away (and all occurrences below replaced by 0),
 * but that would force many users to use the `setkeycodes' utility, where
 * they needed not before. It does not matter that there are duplicates, as
 * long as no duplication occurs for any single keyboard.
 */
#define SC_LIM 89

#define FOCUS_PF1 85           /* actual code! */
#define FOCUS_PF2 89
#define FOCUS_PF3 90
#define FOCUS_PF4 91
#define FOCUS_PF5 92
#define FOCUS_PF6 93
#define FOCUS_PF7 94
#define FOCUS_PF8 95
#define FOCUS_PF9 120
#define FOCUS_PF10 121
#define FOCUS_PF11 122
#define FOCUS_PF12 123

#define JAP_86     124
/* tfj@olivia.ping.dk:
 * The four keys are located over the numeric keypad, and are
 * labelled A1-A4. It's an rc930 keyboard, from
 * Regnecentralen/RC International, Now ICL.
 * Scancodes: 59, 5a, 5b, 5c.
 */
#define RGN1 124
#define RGN2 125
#define RGN3 126
#define RGN4 127

static unsigned char high_keys[128 - SC_LIM] = {
  RGN1, RGN2, RGN3, RGN4, 0, 0, 0,                   /* 0x59-0x5f */
  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x60-0x67 */
  0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,          /* 0x68-0x6f */
  0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,    /* 0x70-0x77 */
  FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,        /* 0x78-0x7b */
  FOCUS_PF8, JAP_86, FOCUS_PF10, 0                   /* 0x7c-0x7f */
};

/* BTC */
#define E0_MACRO   112
/* LK450 */
#define E0_F13     113
#define E0_F14     114
#define E0_HELP    115
#define E0_DO      116
#define E0_F17     117
#define E0_KPMINPLUS 118
/*
 * My OmniKey generates e0 4c for  the "OMNI" key and the
 * right alt key does nada. [kkoller@nyx10.cs.du.edu]
 */
#define E0_OK    124
/*
 * New microsoft keyboard is rumoured to have
 * e0 5b (left window button), e0 5c (right window button),
 * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
 * [or: Windows_L, Windows_R, TaskMan]
 */
#define E0_MSLW    125
#define E0_MSRW    126
#define E0_MSTM    127

static unsigned char e0_keys[128] = {
  0, 0, 0, 0, 0, 0, 0, 0,                  /* 0x00-0x07 */
  0, 0, 0, 0, 0, 0, 0, 0,                  /* 0x08-0x0f */
  0, 0, 0, 0, 0, 0, 0, 0,                  /* 0x10-0x17 */
  0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,          /* 0x18-0x1f */
  0, 0, 0, 0, 0, 0, 0, 0,                  /* 0x20-0x27 */
  0, 0, 0, 0, 0, 0, 0, 0,                  /* 0x28-0x2f */
  0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,          /* 0x30-0x37 */
  E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,          /* 0x38-0x3f */
  E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,          /* 0x40-0x47 */
  E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
  E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,          /* 0x50-0x57 */
  0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0,          /* 0x58-0x5f */
  0, 0, 0, 0, 0, 0, 0, 0,                  /* 0x60-0x67 */
  0, 0, 0, 0, 0, 0, 0, E0_MACRO,              /* 0x68-0x6f */
  0, 0, 0, 0, 0, 0, 0, 0,                  /* 0x70-0x77 */
  0, 0, 0, 0, 0, 0, 0, 0                  /* 0x78-0x7f */
};

/* Simple translation table for the SysRq keys */

#ifdef CONFIG_MAGIC_SYSRQ
unsigned char pcikbd_sysrq_xlate[128] =
    "\000\0331234567890-=\177\t"            /* 0x00 - 0x0f */
    "qwertyuiop[]\r\000as"                /* 0x10 - 0x1f */
    "dfghjkl;'`\000\\zxcv"                /* 0x20 - 0x2f */
    "bnm,./\000*\000 \000\201\202\203\204\205"    /* 0x30 - 0x3f */
    "\206\207\210\211\212\000\000789-456+1"        /* 0x40 - 0x4f */
    "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
    "\r\000/";                    /* 0x60 - 0x6f */
#endif

#define DEFAULT_KEYB_REP_DELAY    250
#define DEFAULT_KEYB_REP_RATE    30    /* cps */

static struct kbd_repeat kbdrate = {
    DEFAULT_KEYB_REP_DELAY,
    DEFAULT_KEYB_REP_RATE
};

static unsigned char parse_kbd_rate(struct kbd_repeat *r);
static int write_kbd_rate(unsigned char r);

int pcikbd_setkeycode(unsigned int scancode, unsigned int keycode)
{
    if(scancode < SC_LIM || scancode > 255 || keycode > 127)
        return -EINVAL;
    if(scancode < 128)
        high_keys[scancode - SC_LIM] = keycode;
    else
        e0_keys[scancode - 128] = keycode;
    return 0;
}

int pcikbd_getkeycode(unsigned int scancode)
{
    return
        (scancode < SC_LIM || scancode > 255) ? -EINVAL :
        (scancode < 128) ? high_keys[scancode - SC_LIM] :
        e0_keys[scancode - 128];
}

static int do_acknowledge(unsigned char scancode)
{
    if(reply_expected) {
        if(scancode == KBD_REPLY_ACK) {
            acknowledge = 1;
            reply_expected = 0;
            return 0;
        } else if(scancode == KBD_REPLY_RESEND) {
            resend = 1;
            reply_expected = 0;
            return 0;
        }
    }
    return 1;
}

#ifdef __sparc_v9__
static void pcikbd_enter_prom(void)
{
    pcikbd_write(KBD_DATA_REG, KBD_CMD_DISABLE);
    if(pcikbd_wait_for_input() != KBD_REPLY_ACK)
        printk("Prom Enter: Disable keyboard: no ACK\n");

    /* Disable PC scancode translation */
    pcikbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE);
    pcikbd_write(KBD_DATA_REG, KBD_MODE_SYS);
    pcikbd_write(KBD_DATA_REG, KBD_CMD_ENABLE);
    if (pcikbd_wait_for_input() != KBD_REPLY_ACK)
        printk("Prom Enter: Enable Keyboard: no ACK\n");
}
#endif

static void ctrl_break(void)
{
    extern int stop_a_enabled;
    unsigned long timeout;
    int status, data;
    int mode;

    if (!stop_a_enabled)
        return;

    pcikbd_write(KBD_DATA_REG, KBD_CMD_DISABLE);
    if(pcikbd_wait_for_input() != KBD_REPLY_ACK)
        printk("Prom Enter: Disable keyboard: no ACK\n");

    /* Save current mode register settings */
    pcikbd_write(KBD_CNTL_REG, KBD_CCMD_READ_MODE);
    if ((mode = pcikbd_wait_for_input()) == -1)
        printk("Prom Enter: Read Mode: no ACK\n");

    /* Disable PC scancode translation */
    pcikbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE);
    pcikbd_write(KBD_DATA_REG, mode & ~(KBD_MODE_KCC));
    pcikbd_write(KBD_DATA_REG, KBD_CMD_ENABLE);
    if (pcikbd_wait_for_input() != KBD_REPLY_ACK)
        printk("Prom Enter: Enable Keyboard: no ACK\n");

    /* Drop into OBP.
     * Note that we must flush the user windows
     * first before giving up control.
     */
        flush_user_windows();
    prom_cmdline();

    /* Read prom's key up event (use short timeout) */
    do {
        timeout = 10;
        do {
            mdelay(1);
            status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);
            if (!(status & KBD_STAT_OBF))
                continue;
            data = pcikbd_inb(pcikbd_iobase + KBD_DATA_REG);
            if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
                continue;
            break;
        } while (--timeout > 0);
    } while (timeout > 0);

    /* Reenable PC scancode translation */
    pcikbd_write(KBD_DATA_REG, KBD_CMD_DISABLE);
    if(pcikbd_wait_for_input() != KBD_REPLY_ACK)
        printk("Prom Leave: Disable keyboard: no ACK\n");

    pcikbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE);
    pcikbd_write(KBD_DATA_REG, mode);
    pcikbd_write(KBD_DATA_REG, KBD_CMD_ENABLE);
    if (pcikbd_wait_for_input() != KBD_REPLY_ACK)
        printk("Prom Leave: Enable Keyboard: no ACK\n");

    /* Reset keyboard rate */
    write_kbd_rate(parse_kbd_rate(&kbdrate));
}

int pcikbd_translate(unsigned char scancode, unsigned char *keycode,
             char raw_mode)
{
    static int prev_scancode = 0;
    int down = scancode & 0x80 ? 0 : 1;

    if (scancode == 0xe0 || scancode == 0xe1) {
        prev_scancode = scancode;
        return 0;
    }
    if (scancode == 0x00 || scancode == 0xff) {
        prev_scancode = 0;
        return 0;
    }
    scancode &= 0x7f;
    if(prev_scancode) {
        if(prev_scancode != 0xe0) {
            if(prev_scancode == 0xe1 && scancode == 0x1d) {
                prev_scancode = 0x100;
                return 0;
            } else if(prev_scancode == 0x100 && scancode == 0x45) {
                *keycode = E1_PAUSE;
                prev_scancode = 0;
            } else {
                prev_scancode = 0;
                return 0;
            }
        } else {
            prev_scancode = 0;
            if(scancode == 0x2a || scancode == 0x36)
                return 0;
            if(e0_keys[scancode])
                *keycode = e0_keys[scancode];
            else
                return 0;
        }
    } else if(scancode >= SC_LIM) {
        *keycode = high_keys[scancode - SC_LIM];
        if(!*keycode)
            return 0;

    } else
        *keycode = scancode;

    if (*keycode == E0_BREAK) {
        if (down)
            return 0;

        /* Handle ctrl-break event */
        ctrl_break();

        /* Send ctrl up event to the keyboard driver */
        *keycode = 0x1d;
    }

    return 1;
}

char pcikbd_unexpected_up(unsigned char keycode)
{
    if(keycode >= SC_LIM || keycode == 85)
        return 0;
    else
        return 0200;
}

static void
pcikbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
    unsigned long flags;
    unsigned char status;

    spin_lock_irqsave(&pcikbd_lock, flags);

    kbd_pt_regs = regs;
    status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);
    do {
        unsigned char scancode;

        if(status & pckbd_read_mask & KBD_STAT_MOUSE_OBF)
            break;
        scancode = pcikbd_inb(pcikbd_iobase + KBD_DATA_REG);
        if((status & KBD_STAT_OBF) && do_acknowledge(scancode))
            handle_scancode(scancode, !(scancode & 0x80));
        status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);
    } while(status & KBD_STAT_OBF);
    tasklet_schedule(&keyboard_tasklet);

    spin_unlock_irqrestore(&pcikbd_lock, flags);
}

static int send_data(unsigned char data)
{
    int retries = 3;
    unsigned long flags;

    do {
        unsigned long timeout = 1000;

        spin_lock_irqsave(&pcikbd_lock, flags);

        kb_wait();

        acknowledge = 0;
        resend = 0;
        reply_expected = 1;

        pcikbd_outb(data, pcikbd_iobase + KBD_DATA_REG);

        spin_unlock_irqrestore(&pcikbd_lock, flags);

        do {
            if (acknowledge)
                return 1;
            if (resend)
                break;
            mdelay(1);
        } while (--timeout);

        if (timeout == 0)
            break;

    } while (retries-- > 0);

    return 0;
}

void pcikbd_leds(unsigned char leds)
{
    if (!pcikbd_iobase)
        return;
    if (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds))
        send_data(KBD_CMD_ENABLE);
}

static unsigned char parse_kbd_rate(struct kbd_repeat *r)
{
    static struct r2v {
        int rate;
        unsigned char val;
    } kbd_rates[]={    { 5,  0x14 },
            { 7,  0x10 },
            { 10, 0x0c },
            { 15, 0x08 },
            { 20, 0x04 },
            { 25, 0x02 },
            { 30, 0x00 } };
    static struct d2v {
        int delay;
        unsigned char val;
    } kbd_delays[]={ { 250,  0 },
             { 500,  1 },
             { 750,  2 },
             { 1000, 3 } };
    int rate = 0, delay = 0;

    if (r != NULL) {
        int i, new_rate = 30, new_delay = 250;
        if (r->rate <= 0)
            r->rate = kbdrate.rate;
        if (r->delay <= 0)
            r->delay = kbdrate.delay;

        for (i = 0; i < sizeof(kbd_rates) / sizeof(struct r2v); i++) {
            if (kbd_rates[i].rate == r->rate) {
                new_rate = kbd_rates[i].rate;
                rate = kbd_rates[i].val;
                break;
            }
        }
        for (i=0; i < sizeof(kbd_delays) / sizeof(struct d2v); i++) {
            if (kbd_delays[i].delay == r->delay) {
                new_delay = kbd_delays[i].delay;
                delay = kbd_delays[i].val;
                break;
            }
        }
        r->rate = new_rate;
        r->delay = new_delay;
    }
    return (delay << 5) | rate;
}

static int write_kbd_rate(unsigned char r)
{
    if (!send_data(KBD_CMD_SET_RATE) || !send_data(r)) {
        /* re-enable kbd if any errors */
        send_data(KBD_CMD_ENABLE);
        return 0;
    }

    return 1;
}

static int pcikbd_rate(struct kbd_repeat *rep)
{
    unsigned char r;
    struct kbd_repeat old_rep;

    if (rep == NULL)
        return -EINVAL;

    r = parse_kbd_rate(rep);
    memcpy(&old_rep, &kbdrate, sizeof(struct kbd_repeat));
    if (write_kbd_rate(r)) {
        memcpy(&kbdrate,rep,sizeof(struct kbd_repeat));
        memcpy(rep,&old_rep,sizeof(struct kbd_repeat));
        return 0;
    }

    return -EIO;
}

static int pcikbd_wait_for_input(void)
{
    int status, data;
    unsigned long timeout = 1000;

    do {
        mdelay(1);

        status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);
        if (!(status & KBD_STAT_OBF))
            continue;

        data = pcikbd_inb(pcikbd_iobase + KBD_DATA_REG);
        if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
            continue;

        return (data & 0xff);

    } while (--timeout > 0);

    return -1;
}

static void pcikbd_write(int address, int data)
{
    int status;

    do {
        status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);
    } while (status & KBD_STAT_IBF);
    pcikbd_outb(data, pcikbd_iobase + address);
}

#ifdef __sparc_v9__

static unsigned long pcibeep_iobase = 0;

/* Timer routine to turn off the beep after the interval expires. */
static void pcikbd_kd_nosound(unsigned long __unused)
{
    if (pcibeep_iobase & 0x2UL)
        outb(0, pcibeep_iobase);
    else
        outl(0, pcibeep_iobase);
}

/*
 * Initiate a keyboard beep. If the frequency is zero, then we stop
 * the beep. Any other frequency will start a monotone beep. The beep
 * will be stopped by a timer after "ticks" jiffies. If ticks is 0,
 * then we do not start a timer.
 */
static void pcikbd_kd_mksound(unsigned int hz, unsigned int ticks)
{
    unsigned long flags;
    static struct timer_list sound_timer = { function: pcikbd_kd_nosound };

    save_flags(flags); cli();
    del_timer(&sound_timer);
    if (hz) {
        if (pcibeep_iobase & 0x2UL)
            outb(1, pcibeep_iobase);
        else
            outl(1, pcibeep_iobase);
        if (ticks) {
            sound_timer.expires = jiffies + ticks;
            add_timer(&sound_timer);
        }
    } else {
        if (pcibeep_iobase & 0x2UL)
            outb(0, pcibeep_iobase);
        else
            outl(0, pcibeep_iobase);
    }
    restore_flags(flags);
}

#if defined(CONFIG_USB) && defined(CONFIG_SPARC64)
static void isa_kd_nosound(unsigned long __unused)
{
    /* disable counter 2 */
    outb(inb(pcibeep_iobase + 0x61)&0xFC, pcibeep_iobase + 0x61);
    return;
}

static void isa_kd_mksound(unsigned int hz, unsigned int ticks)
{
    static struct timer_list sound_timer = { function: isa_kd_nosound };
    unsigned int count = 0;
    unsigned long flags;

    if (hz > 20 && hz < 32767)
        count = 1193180 / hz;
    
    save_flags(flags);
    cli();
    del_timer(&sound_timer);
    if (count) {
        /* enable counter 2 */
        outb(inb(pcibeep_iobase + 0x61)|3, pcibeep_iobase + 0x61);
        /* set command for counter 2, 2 byte write */
        outb(0xB6, pcibeep_iobase + 0x43);
        /* select desired HZ */
        outb(count & 0xff, pcibeep_iobase + 0x42);
        outb((count >> 8) & 0xff, pcibeep_iobase + 0x42);

        if (ticks) {
            sound_timer.expires = jiffies+ticks;
            add_timer(&sound_timer);
        }
    } else
        isa_kd_nosound(0);
    restore_flags(flags);
    return;
}
#endif

#endif

static void nop_kd_mksound(unsigned int hz, unsigned int ticks)
{
}

extern void (*kd_mksound)(unsigned int hz, unsigned int ticks);

static char * __init do_pcikbd_init_hw(void)
{

    while(pcikbd_wait_for_input() != -1)
        ;

    pcikbd_write(KBD_CNTL_REG, KBD_CCMD_SELF_TEST);
    if(pcikbd_wait_for_input() != 0x55)
        return "Keyboard failed self test";

    pcikbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_TEST);
    if(pcikbd_wait_for_input() != 0x00)
        return "Keyboard interface failed self test";

    pcikbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_ENABLE);
    pcikbd_write(KBD_DATA_REG, KBD_CMD_RESET);
    if(pcikbd_wait_for_input() != KBD_REPLY_ACK)
        return "Keyboard reset failed, no ACK";
    if(pcikbd_wait_for_input() != KBD_REPLY_POR)
        return "Keyboard reset failed, no ACK";

    pcikbd_write(KBD_DATA_REG, KBD_CMD_DISABLE);
    if(pcikbd_wait_for_input() != KBD_REPLY_ACK)
        return "Disable keyboard: no ACK";

    pcikbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE);
    pcikbd_write(KBD_DATA_REG,
             (KBD_MODE_KBD_INT | KBD_MODE_SYS |
              KBD_MODE_DISABLE_MOUSE | KBD_MODE_KCC));
    pcikbd_write(KBD_DATA_REG, KBD_CMD_ENABLE);
    if(pcikbd_wait_for_input() != KBD_REPLY_ACK)
        return "Enable keyboard: no ACK";

    write_kbd_rate(parse_kbd_rate(&kbdrate));

    return NULL; /* success */
}

void __init pcikbd_init_hw(void)
{
    struct linux_ebus *ebus;
    struct linux_ebus_device *edev;
    struct linux_ebus_child *child;
    char *msg;

    if (pcikbd_mrcoffee) {
        if ((pcikbd_iobase = (unsigned long) ioremap(0x71300060, 8)) == 0) {
            prom_printf("pcikbd_init_hw: cannot map\n");
            return;
        }
        pcikbd_irq = 13 | 0x20;
        if (request_irq(pcikbd_irq, &pcikbd_interrupt,
                SA_SHIRQ, "keyboard", (void *)pcikbd_iobase)) {
            printk("8042: cannot register IRQ %x\n", pcikbd_irq);
            return;
        }
        printk("8042(kbd): iobase[%x] irq[%x]\n",
            (unsigned)pcikbd_iobase, pcikbd_irq);
    } else {
        for_each_ebus(ebus) {
            for_each_ebusdev(edev, ebus) {
                if(!strcmp(edev->prom_name, "8042")) {
                    for_each_edevchild(edev, child) {
                                                if (strcmp(child->prom_name, PCI_KB_NAME1) == 0 ||
                            strcmp(child->prom_name, PCI_KB_NAME2) == 0)
                            goto found;
                    }
                }
            }
        }
#ifdef CONFIG_USB
        /* We are being called for the sake of USB keyboard
         * state initialization.  So we should check for beeper
         * device in this case.
         */
        edev = 0;
        for_each_ebus(ebus) {
            for_each_ebusdev(edev, ebus) {
                if (!strcmp(edev->prom_name, "beep")) {
                    pcibeep_iobase = edev->resource[0].start;
                    kd_mksound = pcikbd_kd_mksound;
                    printk("8042(speaker): iobase[%016lx]\n", pcibeep_iobase);
                    return;
                }
            }
        }

#ifdef CONFIG_SPARC64
        /* Maybe we have one inside the ALI southbridge? */
        {
            struct isa_bridge *isa_br;
            struct isa_device *isa_dev;
            for_each_isa(isa_br) {
                for_each_isadev(isa_dev, isa_br) {
                    /* This is a hack, the 'dma' device node has
                     * the base of the I/O port space for that PBM
                     * as it's resource, so we use that. -DaveM
                     */
                    if (!strcmp(isa_dev->prom_name, "dma")) {
                        pcibeep_iobase = isa_dev->resource.start;
                        kd_mksound = isa_kd_mksound;
                        printk("isa(speaker): iobase[%016lx:%016lx]\n",
                               pcibeep_iobase + 0x42,
                               pcibeep_iobase + 0x61);
                        return;
                    }
                }
            }
        }
#endif

        /* No beeper found, ok complain. */
#endif
        printk("pcikbd_init_hw: no 8042 found\n");
        return;

found:
        pcikbd_iobase = child->resource[0].start;
        pcikbd_irq = child->irqs[0];
        if (request_irq(pcikbd_irq, &pcikbd_interrupt,
                SA_SHIRQ, "keyboard", (void *)pcikbd_iobase)) {
            printk("8042: cannot register IRQ %s\n",
                   __irq_itoa(pcikbd_irq));
            return;
        }

        printk("8042(kbd) at 0x%lx (irq %s)\n", pcikbd_iobase,
               __irq_itoa(pcikbd_irq));
    }

    kd_mksound = nop_kd_mksound;
    kbd_rate = pcikbd_rate;

#ifdef __sparc_v9__
    edev = 0;
    for_each_ebus(ebus) {
        for_each_ebusdev(edev, ebus) {
            if(!strcmp(edev->prom_name, "beeper"))
                goto ebus_done;
        }
    }
ebus_done:

    /*
     * XXX: my 3.1.3 PROM does not give me the beeper node for the audio
     *      auxio register, though I know it is there... (ecd)
     *
     * JavaStations appear not to have beeper. --zaitcev
     */
    if (!edev)
        pcibeep_iobase = (pcikbd_iobase & ~(0xffffff)) | 0x722000;
    else
        pcibeep_iobase = edev->resource[0].start;

    kd_mksound = pcikbd_kd_mksound;
    printk("8042(speaker): iobase[%016lx]%s\n", pcibeep_iobase,
           edev ? "" : " (forced)");

    prom_keyboard = pcikbd_enter_prom;
#endif

    disable_irq(pcikbd_irq);
    msg = do_pcikbd_init_hw();
    enable_irq(pcikbd_irq);

    if(msg)
        printk("8042: keyboard init failure [%s]\n", msg);
}


/*
 * Here begins the Mouse Driver.
 */

static unsigned long pcimouse_iobase = 0;
static unsigned int pcimouse_irq;

#define AUX_BUF_SIZE    2048

struct aux_queue {
    unsigned long head;
    unsigned long tail;
    wait_queue_head_t proc_list;
    struct fasync_struct *fasync;
    unsigned char buf[AUX_BUF_SIZE];
};

static struct aux_queue *queue;
static int aux_count = 0;
static int aux_present = 0;

#define pcimouse_inb(x)     inb(x)
#define pcimouse_outb(v,x)  outb(v,x)

/*
 *    Shared subroutines
 */

static unsigned int get_from_queue(void)
{
    unsigned int result;
    unsigned long flags;

    spin_lock_irqsave(&pcikbd_lock, flags);
    result = queue->buf[queue->tail];
    queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
    spin_unlock_irqrestore(&pcikbd_lock, flags);

    return result;
}


static inline int queue_empty(void)
{
    return queue->head == queue->tail;
}

static int aux_fasync(int fd, struct file *filp, int on)
{
    int retval;

    retval = fasync_helper(fd, filp, on, &queue->fasync);
    if (retval < 0)
        return retval;
    return 0;
}

/*
 *    PS/2 Aux Device
 */

#define AUX_INTS_OFF    (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | \
             KBD_MODE_SYS | KBD_MODE_KBD_INT)

#define AUX_INTS_ON    (KBD_MODE_KCC | KBD_MODE_SYS | \
             KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)

#define MAX_RETRIES    60        /* some aux operations take long time*/

/*
 *    Status polling
 */

static int poll_aux_status(void)
{
    int retries = 0;

    while ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) &
        (KBD_STAT_IBF | KBD_STAT_OBF)) && retries < MAX_RETRIES) {
         if ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF)
            == AUX_STAT_OBF)
            pcimouse_inb(pcimouse_iobase + KBD_DATA_REG);
        mdelay(5);
        retries++;
    }

    return (retries < MAX_RETRIES);
}

/*
 * Write to aux device
 */

static void aux_write_dev(int val)
{
    poll_aux_status();
    pcimouse_outb(KBD_CCMD_WRITE_MOUSE, pcimouse_iobase + KBD_CNTL_REG);/* Write magic cookie */
    poll_aux_status();
    pcimouse_outb(val, pcimouse_iobase + KBD_DATA_REG);         /* Write data */
    udelay(1);
}

/*
 * Write to device & handle returned ack
 */

static int __init aux_write_ack(int val)
{
    aux_write_dev(val);
    poll_aux_status();

    if ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF) == AUX_STAT_OBF)
        return (pcimouse_inb(pcimouse_iobase + KBD_DATA_REG));
    return 0;
}

/*
 * Write aux device command
 */

static void aux_write_cmd(int val)
{
    poll_aux_status();
    pcimouse_outb(KBD_CCMD_WRITE_MODE, pcimouse_iobase + KBD_CNTL_REG);
    poll_aux_status();
    pcimouse_outb(val, pcimouse_iobase + KBD_DATA_REG);
}

/*
 * Interrupt from the auxiliary device: a character
 * is waiting in the keyboard/aux controller.
 */

void pcimouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
    unsigned long flags;
    int head, maxhead;
    unsigned char val;

    spin_lock_irqsave(&pcikbd_lock, flags);

    head = queue->head;
    maxhead = (queue->tail - 1) & (AUX_BUF_SIZE - 1);

    if ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF) !=
        AUX_STAT_OBF) {
        spin_unlock_irqrestore(&pcikbd_lock, flags);
        return;
    }

    val = pcimouse_inb(pcimouse_iobase + KBD_DATA_REG);
    queue->buf[head] = val;
    add_mouse_randomness(val);
    if (head != maxhead) {
        head++;
        head &= AUX_BUF_SIZE - 1;
    }
    queue->head = head;

    spin_unlock_irqrestore(&pcikbd_lock, flags);

    kill_fasync(&queue->fasync, SIGIO, POLL_IN);
    wake_up_interruptible(&queue->proc_list);
}

static int aux_release(struct inode * inode, struct file * file)
{
    unsigned long flags;

    aux_fasync(-1, file, 0);

    spin_lock_irqsave(&pcikbd_lock, flags);

    if (--aux_count)
        goto out;

    /* Disable controller ints */
    aux_write_cmd(AUX_INTS_OFF);
    poll_aux_status();

    /* Disable Aux device */
    pcimouse_outb(KBD_CCMD_MOUSE_DISABLE, pcimouse_iobase + KBD_CNTL_REG);
    poll_aux_status();

out:
    spin_unlock_irqrestore(&pcikbd_lock, flags);

    return 0;
}

/*
 * Install interrupt handler.
 * Enable auxiliary device.
 */

static int aux_open(struct inode * inode, struct file * file)
{
    unsigned long flags;

    if (!aux_present)
        return -ENODEV;

    spin_lock_irqsave(&pcikbd_lock, flags);

    if (aux_count++) {
        spin_unlock_irqrestore(&pcikbd_lock, flags);
        return 0;
    }

    if (!poll_aux_status()) {
        aux_count--;
        spin_unlock_irqrestore(&pcikbd_lock, flags);
        return -EBUSY;
    }
    queue->head = queue->tail = 0;        /* Flush input queue */

    poll_aux_status();
    pcimouse_outb(KBD_CCMD_MOUSE_ENABLE, pcimouse_iobase+KBD_CNTL_REG);    /* Enable Aux */
    aux_write_dev(AUX_ENABLE_DEV);                /* Enable aux device */
    aux_write_cmd(AUX_INTS_ON);                /* Enable controller ints */
    poll_aux_status();

    spin_unlock_irqrestore(&pcikbd_lock, flags);


    return 0;
}

/*
 * Write to the aux device.
 */

static ssize_t aux_write(struct file * file, const char * buffer,
             size_t count, loff_t *ppos)
{
    ssize_t retval = 0;
    unsigned long flags;

    if (count) {
        ssize_t written = 0;

        spin_lock_irqsave(&pcikbd_lock, flags);

        do {
            char c;

            spin_unlock_irqrestore(&pcikbd_lock, flags);

            get_user(c, buffer++);

            spin_lock_irqsave(&pcikbd_lock, flags);

            if (!poll_aux_status())
                break;
            pcimouse_outb(KBD_CCMD_WRITE_MOUSE,
                      pcimouse_iobase + KBD_CNTL_REG);
            if (!poll_aux_status())
                break;

            pcimouse_outb(c, pcimouse_iobase + KBD_DATA_REG);
            written++;
        } while (--count);

        spin_unlock_irqrestore(&pcikbd_lock, flags);

        retval = -EIO;
        if (written) {
            retval = written;
            file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
        }
    }

    return retval;
}

/*
 *    Generic part continues...
 */

/*
 * Put bytes from input queue to buffer.
 */

static ssize_t aux_read(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;
}

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 = {
    owner:        THIS_MODULE,
    read:        aux_read,
    write:        aux_write,
    poll:        aux_poll,
    open:        aux_open,
    release:    aux_release,
    fasync:        aux_fasync,
};

static int aux_no_open(struct inode *inode, struct file *file)
{
    return -ENODEV;
}

struct file_operations psaux_no_fops = {
    owner:        THIS_MODULE,
    open:        aux_no_open,
};

static struct miscdevice psaux_mouse = {
    PSMOUSE_MINOR, "ps2aux", &psaux_fops
};

static struct miscdevice psaux_no_mouse = {
    PSMOUSE_MINOR, "ps2aux", &psaux_no_fops
};

int __init pcimouse_init(void)
{
    struct linux_ebus *ebus;
    struct linux_ebus_device *edev;
    struct linux_ebus_child *child;

    if (pcikbd_mrcoffee) {
        if ((pcimouse_iobase = pcikbd_iobase) == 0) {
            printk("pcimouse_init: no 8042 given\n");
            goto do_enodev;
        }
        pcimouse_irq = pcikbd_irq;
    } else {
        for_each_ebus(ebus) {
            for_each_ebusdev(edev, ebus) {
                if(!strcmp(edev->prom_name, "8042")) {
                    for_each_edevchild(edev, child) {
                            if (strcmp(child->prom_name, PCI_MS_NAME1) == 0 ||
                                strcmp(child->prom_name, PCI_MS_NAME2) == 0)
                            goto found;
                    }
                }
            }
        }
        printk("pcimouse_init: no 8042 found\n");
        goto do_enodev;

found:
        pcimouse_iobase = child->resource[0].start;
        pcimouse_irq = child->irqs[0];
    }

    queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
    if (!queue) {
        printk("pcimouse_init: kmalloc(aux_queue) failed.\n");
        return -ENOMEM;
    }
    memset(queue, 0, sizeof(*queue));

    init_waitqueue_head(&queue->proc_list);

    if (request_irq(pcimouse_irq, &pcimouse_interrupt,
                SA_SHIRQ, "mouse", (void *)pcimouse_iobase)) {
        printk("8042: Cannot register IRQ %s\n",
               __irq_itoa(pcimouse_irq));
        goto do_enodev;
    }

    printk("8042(mouse) at %lx (irq %s)\n", pcimouse_iobase,
           __irq_itoa(pcimouse_irq));

    printk("8042: PS/2 auxiliary pointing device detected.\n");
    aux_present = 1;
    pckbd_read_mask = AUX_STAT_OBF;

    misc_register(&psaux_mouse);

    spin_lock_irq(&pcikbd_lock);

    pcimouse_outb(KBD_CCMD_MOUSE_ENABLE, pcimouse_iobase + KBD_CNTL_REG);
    aux_write_ack(AUX_RESET);
    aux_write_ack(AUX_SET_SAMPLE);
    aux_write_ack(100);
    aux_write_ack(AUX_SET_RES);
    aux_write_ack(3);
    aux_write_ack(AUX_SET_SCALE21);
    poll_aux_status();
    pcimouse_outb(KBD_CCMD_MOUSE_DISABLE, pcimouse_iobase + KBD_CNTL_REG);
    poll_aux_status();
    pcimouse_outb(KBD_CCMD_WRITE_MODE, pcimouse_iobase + KBD_CNTL_REG);
    poll_aux_status();
    pcimouse_outb(AUX_INTS_OFF, pcimouse_iobase + KBD_DATA_REG);
    poll_aux_status();

    spin_unlock_irq(&pcikbd_lock);

    return 0;

do_enodev:
    misc_register(&psaux_no_mouse);
    return -ENODEV;
}

int __init pcimouse_no_init(void)
{
    misc_register(&psaux_no_mouse);
    return -ENODEV;
}

int __init ps2kbd_probe(void)
{
    int pnode, enode, node, dnode, xnode;
    int kbnode = 0, msnode = 0, bnode = 0;
    int devices = 0;
    char prop[128];
    int len;

#ifndef __sparc_v9__
    /*
     * MrCoffee has hardware but has no PROM nodes whatsoever.
     */
    len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop));
    if (len < 0) {
        printk("ps2kbd_probe: no name of root node\n");
        goto do_enodev;
    }
    if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) {
        pcikbd_mrcoffee = 1;    /* Brain damage detected */
        goto found;
    }
#endif
    /*
     * Get the nodes for keyboard and mouse from aliases on normal systems.
     */
        node = prom_getchild(prom_root_node);
    node = prom_searchsiblings(node, "aliases");
    if (!node)
        goto do_enodev;

    len = prom_getproperty(node, "keyboard", prop, sizeof(prop));
    if (len > 0) {
        prop[len] = 0;
        kbnode = prom_finddevice(prop);
    }
    if (!kbnode)
        goto do_enodev;

    len = prom_getproperty(node, "mouse", prop, sizeof(prop));
    if (len > 0) {
        prop[len] = 0;
        msnode = prom_finddevice(prop);
    }
    if (!msnode)
        goto do_enodev;

    /*
     * Find matching EBus nodes...
     */
        node = prom_getchild(prom_root_node);
    pnode = prom_searchsiblings(node, "pci");

    /*
     * Check for SUNW,sabre on Ultra5/10/AXi.
     */
    len = prom_getproperty(pnode, "model", prop, sizeof(prop));
    if ((len > 0) && !strncmp(prop, "SUNW,sabre", len)) {
        pnode = prom_getchild(pnode);
        pnode = prom_searchsiblings(pnode, "pci");
    }

    /*
     * For each PCI bus...
     */
    while (pnode) {
        enode = prom_getchild(pnode);
        enode = prom_searchsiblings(enode, "ebus");

        /*
         * For each EBus on this PCI...
         */
        while (enode) {
            node = prom_getchild(enode);
            bnode = prom_searchsiblings(node, "beeper");

            node = prom_getchild(enode);
            node = prom_searchsiblings(node, "8042");

            /*
             * For each '8042' on this EBus...
             */
            while (node) {
                dnode = prom_getchild(node);

                /*
                 * Does it match?
                 */
                if ((xnode = prom_searchsiblings(dnode, PCI_KB_NAME1)) == kbnode) {
                    ++devices;
                } else if ((xnode = prom_searchsiblings(dnode, PCI_KB_NAME2)) == kbnode) {
                    ++devices;
                }

                if ((xnode = prom_searchsiblings(dnode, PCI_MS_NAME1)) == msnode) {
                    ++devices;
                } else if ((xnode = prom_searchsiblings(dnode, PCI_MS_NAME2)) == msnode) {
                    ++devices;
                }

                /*
                 * Found everything we need?
                 */
                if (devices == 2)
                    goto found;

                node = prom_getsibling(node);
                node = prom_searchsiblings(node, "8042");
            }
            enode = prom_getsibling(enode);
            enode = prom_searchsiblings(enode, "ebus");
        }
        pnode = prom_getsibling(pnode);
        pnode = prom_searchsiblings(pnode, "pci");
    }
do_enodev:
    sunkbd_setinitfunc(pcimouse_no_init);
    return -ENODEV;

found:
        sunkbd_setinitfunc(pcimouse_init);
        sunkbd_setinitfunc(pcikbd_init);
    kbd_ops.compute_shiftstate = pci_compute_shiftstate;
    kbd_ops.setledstate = pci_setledstate;
    kbd_ops.getledstate = pci_getledstate;
    kbd_ops.setkeycode = pci_setkeycode;
    kbd_ops.getkeycode = pci_getkeycode;
    return 0;
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.0486 ]--