!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/char/   drwxr-xr-x
Free 318.38 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:     hp_psaux.c (12.04 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 *      LASI PS/2 keyboard/psaux driver for HP-PARISC workstations
 *      
 *      (c) Copyright 1999 The Puffin Group Inc.
 *      by Alex deVries <adevries@thepuffingroup.com>
 *    Copyright 1999, 2000 Philipp Rumpf <prumpf@tux.org>
 *
 *    2000/10/26    Debacker Xavier (debackex@esiee.fr)
 *            Marteau Thomas (marteaut@esiee.fr)
 *             Djoudi Malek (djoudim@esiee.fr)
 *    fixed leds control
 *    implemented the psaux and controlled the mouse scancode based on pc_keyb.c
 */

#include <linux/config.h>

#include <asm/hardware.h>
#include <asm/keyboard.h>
#include <asm/gsc.h>

#include <linux/types.h>
#include <linux/ptrace.h>    /* interrupt.h wants struct pt_regs defined */
#include <linux/interrupt.h>
#include <linux/sched.h>    /* for request_irq/free_irq */
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/pc_keyb.h>
#include <linux/kbd_kern.h>

/* mouse includes */
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <linux/poll.h>

/* HP specific LASI PS/2 keyboard and psaux constants */
#define    AUX_REPLY_ACK    0xFA    /* Command byte ACK. */
#define    AUX_RECONNECT    0xAA    /* scancode when ps2 device is plugged (back) in */

#define    LASI_PSAUX_OFFSET 0x0100 /* offset from keyboard to psaux port */

#define    LASI_ID        0x00    /* ID and reset port offsets */
#define    LASI_RESET    0x00
#define    LASI_RCVDATA    0x04    /* receive and transmit port offsets */
#define    LASI_XMTDATA    0x04
#define    LASI_CONTROL    0x08    /* see: control register bits */
#define    LASI_STATUS    0x0C    /* see: status register bits */

/* control register bits */
#define LASI_CTRL_ENBL    0x01    /* enable interface */
#define LASI_CTRL_LPBXR    0x02    /* loopback operation */
#define LASI_CTRL_DIAG    0x20    /* directly control clock/data line */
#define LASI_CTRL_DATDIR 0x40    /* data line direct control */
#define LASI_CTRL_CLKDIR 0x80    /* clock line direct control */

/* status register bits */
#define LASI_STAT_RBNE    0x01
#define LASI_STAT_TBNE    0x02
#define LASI_STAT_TERR    0x04
#define LASI_STAT_PERR    0x08
#define LASI_STAT_CMPINTR 0x10
#define LASI_STAT_DATSHD 0x40
#define LASI_STAT_CLKSHD 0x80

static void *lasikbd_hpa;
static void *lasips2_hpa;


static inline u8 read_input(void *hpa)
{
    return gsc_readb(hpa+LASI_RCVDATA);
}

static inline u8 read_control(void *hpa)
{
        return gsc_readb(hpa+LASI_CONTROL);
}

static inline void write_control(u8 val, void *hpa)
{
    gsc_writeb(val, hpa+LASI_CONTROL);
}

static inline u8 read_status(void *hpa)
{
        return gsc_readb(hpa+LASI_STATUS);
}

static int write_output(u8 val, void *hpa)
{
    int wait = 0;

    while (read_status(hpa) & LASI_STAT_TBNE) {
        wait++;
        if (wait>10000) {
            /* printk(KERN_WARNING "Lasi PS/2 transmit buffer timeout\n"); */
            return 0;
        }
    }

    if (wait)
        printk(KERN_DEBUG "Lasi PS/2 wait %d\n", wait);
    
    gsc_writeb(val, hpa+LASI_XMTDATA);

    return 1;
}

/* This function is the PA-RISC adaptation of i386 source */

static inline int aux_write_ack(u8 val)
{
      return write_output(val, lasikbd_hpa+LASI_PSAUX_OFFSET);
}

static void lasikbd_leds(unsigned char leds)
{
    write_output(KBD_CMD_SET_LEDS, lasikbd_hpa);
    write_output(leds, lasikbd_hpa);
    write_output(KBD_CMD_ENABLE, lasikbd_hpa);
}

#if 0
/* this might become useful again at some point.  not now  -prumpf */
int lasi_ps2_test(void *hpa)
{
    u8 control,c;
    int i, ret = 0;

    control = read_control(hpa);
    write_control(control | LASI_CTRL_LPBXR | LASI_CTRL_ENBL, hpa);

    for (i=0; i<256; i++) {
        write_output(i, hpa);

        while (!(read_status(hpa) & LASI_STAT_RBNE))
            /* just wait */;
            
        c = read_input(hpa);
        if (c != i)
            ret--;
    }

    write_control(control, hpa);

    return ret;
}
#endif 

static int __init lasi_ps2_reset(void *hpa, int id)
{
    u8 control;
    int ret = 1;

    /* reset the interface */
    gsc_writeb(0xff, hpa+LASI_RESET);
    gsc_writeb(0x0 , hpa+LASI_RESET);        

    /* enable it */
    control = read_control(hpa);
    write_control(control | LASI_CTRL_ENBL, hpa);

        /* initializes the leds at the default state */
        if (id==0) {
           write_output(KBD_CMD_SET_LEDS, hpa);
       write_output(0, hpa);
       ret = write_output(KBD_CMD_ENABLE, hpa);
    }

    return ret;
}

static int inited;

static void lasi_ps2_init_hw(void)
{
    ++inited;
}


/* Greatly inspired by pc_keyb.c */

/*
 * Wait for keyboard controller input buffer to drain.
 *
 * Don't use 'jiffies' so that we don't depend on
 * interrupts..
 *
 * Quote from PS/2 System Reference Manual:
 *
 * "Address hex 0060 and address hex 0064 should be written only when
 * the input-buffer-full bit and output-buffer-full bit in the
 * Controller Status register are set 0."
 */
#ifdef CONFIG_PSMOUSE

static struct aux_queue    *queue;
static spinlock_t    kbd_controller_lock = SPIN_LOCK_UNLOCKED;
static unsigned char    mouse_reply_expected;
static int         aux_count;

static int fasync_aux(int fd, struct file *filp, int on)
{
    int retval;
    
    retval = fasync_helper(fd, filp, on, &queue->fasync);
    if (retval < 0)
        return retval;
    
    return 0;
}



static inline void handle_mouse_scancode(unsigned char scancode)
{
    if (mouse_reply_expected) {
        if (scancode == AUX_REPLY_ACK) {
            mouse_reply_expected--;
            return;
        }
        mouse_reply_expected = 0;
    }
    else if (scancode == AUX_RECONNECT) {
        queue->head = queue->tail = 0;  /* Flush input queue */
        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 inline int queue_empty(void)
{
    return queue->head == queue->tail;
}

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;
}


/*
 * Write to the aux device.
 */

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

    if (count) {
        ssize_t written = 0;

        if (count > 32)
            count = 32; /* Limit to 32 bytes. */
        do {
            char c;
            get_user(c, buffer++);
            written++;
        } while (--count);
        retval = -EIO;
        if (written) {
            retval = written;
            file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
        }
    }

    return retval;
}



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;
        }
        set_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 int open_aux(struct inode * inode, struct file * file)
{
    if (aux_count++) 
        return 0;

    queue->head = queue->tail = 0;    /* Flush input queue */
    aux_count = 1;
    aux_write_ack(AUX_ENABLE_DEV);    /* Enable aux device */
    
    return 0;
}


/* No kernel lock held - fine */
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;
}


static int release_aux(struct inode * inode, struct file * file)
{
    lock_kernel();
    fasync_aux(-1, file, 0);
    if (--aux_count) {
       unlock_kernel();
        return 0;
    }
    unlock_kernel();
    return 0;
}

static struct file_operations psaux_fops = {
    read:        read_aux,
    write:        write_aux,
    poll:        aux_poll,
    open:        open_aux,
    release:    release_aux,
    fasync:        fasync_aux,
};

static struct miscdevice psaux_mouse = {
    minor:        PSMOUSE_MINOR,
    name:        "psaux",
    fops:        &psaux_fops,
};

#endif /* CONFIG_PSMOUSE */


/* This function is looking at the PS2 controller and empty the two buffers */

static u8 handle_lasikbd_event(void *hpa)
{
        u8 status_keyb,status_mouse,scancode,id;
        extern void handle_at_scancode(int); /* in drivers/char/keyb_at.c */
        
        /* Mask to get the base address of the PS/2 controller */
        id = gsc_readb(hpa+LASI_ID) & 0x0f;
        
        if (id==1) 
           hpa -= LASI_PSAUX_OFFSET; 
        lasikbd_hpa = hpa;
        

        status_keyb = read_status(hpa);
        status_mouse = read_status(hpa+LASI_PSAUX_OFFSET);

        while ((status_keyb|status_mouse) & LASI_STAT_RBNE){
           
           while (status_keyb & LASI_STAT_RBNE) {
          
              scancode = read_input(hpa);

          /* XXX don't know if this is a valid fix, but filtering
           * 0xfa avoids 'unknown scancode' errors on, eg, capslock
           * on some keyboards.
           */
          if (inited && scancode != 0xfa)
         handle_at_scancode(scancode); 
          
          status_keyb =read_status(hpa);
           }
       
#ifdef CONFIG_PSMOUSE
           while (status_mouse & LASI_STAT_RBNE) {
          scancode = read_input(hpa+LASI_PSAUX_OFFSET);
          handle_mouse_scancode(scancode);
              status_mouse = read_status(hpa+LASI_PSAUX_OFFSET);
       }
           status_mouse = read_status(hpa+LASI_PSAUX_OFFSET);
#endif /* CONFIG_PSMOUSE */
           status_keyb = read_status(hpa);
        }

        tasklet_schedule(&keyboard_tasklet);
        return (status_keyb|status_mouse);
}



    
extern struct pt_regs *kbd_pt_regs;

static void lasikbd_interrupt(int irq, void *dev, struct pt_regs *regs)
{
    lasips2_hpa = dev; /* save "hpa" for lasikbd_leds() */
    kbd_pt_regs = regs;
    handle_lasikbd_event(lasips2_hpa);
}


extern int pckbd_translate(unsigned char, unsigned char *, char);

static struct kbd_ops gsc_ps2_kbd_ops = {
    translate:    pckbd_translate,
    init_hw:    lasi_ps2_init_hw,
    leds:        lasikbd_leds,
#ifdef CONFIG_MAGIC_SYSRQ
    sysrq_key:    0x54,
    sysrq_xlate:    hp_ps2kbd_sysrq_xlate,
#endif
};

static int __init
lasi_ps2_register(struct hp_device *d, struct pa_iodc_driver *dri)
{
    void *hpa = (void *) d->hpa;
    unsigned int irq;
    char *name;
    int device_found;
    u8 id;

    id = gsc_readb(hpa+LASI_ID) & 0x0f;

    switch (id) {
    case 0:
        name = "keyboard";
        lasikbd_hpa = hpa;
        break;
    case 1:
        name = "psaux";
        break;
    default:
        printk(KERN_WARNING "%s: Unknown PS/2 port (id=%d) - ignored.\n",
            __FUNCTION__, id );
        return 0;
    }
    
    /* reset the PS/2 port */
    device_found = lasi_ps2_reset(hpa,id);

    /* allocate the irq and memory region for that device */
    if (!(irq = busdevice_alloc_irq(d)))
        return -ENODEV;
            
    if (request_irq(irq, lasikbd_interrupt, 0, name, hpa))
        return -ENODEV;
    
    if (!request_mem_region((unsigned long)hpa, LASI_STATUS + 4, name))
        return -ENODEV;

    switch (id) {
    case 0:    
        register_kbd_ops(&gsc_ps2_kbd_ops);
        break;
    case 1:
#ifdef CONFIG_PSMOUSE
        queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
        if (!queue)
            return -ENOMEM;

        memset(queue, 0, sizeof(*queue));
        queue->head = queue->tail = 0;
        init_waitqueue_head(&queue->proc_list);
        
        misc_register(&psaux_mouse);

        aux_write_ack(AUX_ENABLE_DEV);
        /* try it a second time, this will give status if the device is
         * available */
        device_found = aux_write_ack(AUX_ENABLE_DEV);
        break;
#else
        /* return without printing any unnecessary and misleading info */
        return 0;    
#endif
    } /* of case */
    
    printk(KERN_INFO "PS/2 %s controller at 0x%08lx (irq %d) found, "
             "%sdevice attached.\n",
            name, (unsigned long)hpa, irq,
            device_found ? "":"no ");

    return 0;
}


static struct pa_iodc_driver lasi_psaux_drivers_for[] __initdata = {
    {HPHW_FIO, 0x0, 0,0x00084, 0, 0,
        DRIVER_CHECK_HWTYPE + DRIVER_CHECK_SVERSION,
        "Lasi psaux", "generic", (void *) lasi_ps2_register},
    { 0, }
};

static int __init gsc_ps2_init(void) 
{
    return pdc_register_driver(lasi_psaux_drivers_for);
}

module_init(gsc_ps2_init);


:: 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.0052 ]--