root/drivers/char/psaux.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. aux_write_dev
  2. aux_write_ack
  3. aux_write_cmd
  4. get_from_queue
  5. queue_empty
  6. aux_interrupt
  7. qp_interrupt
  8. release_aux
  9. release_qp
  10. fasync_aux
  11. open_aux
  12. open_qp
  13. write_aux
  14. write_qp
  15. read_aux
  16. aux_select
  17. psaux_init
  18. init_module
  19. cleanup_module
  20. poll_aux_status
  21. poll_aux_status_nosleep
  22. poll_qp_status
  23. read_710
  24. probe_qp

   1 /*
   2  * linux/drivers/char/psaux.c
   3  *
   4  * Driver for PS/2 type mouse by Johan Myreen.
   5  *
   6  * Supports pointing devices attached to a PS/2 type
   7  * Keyboard and Auxiliary Device Controller.
   8  *
   9  * Corrections in device setup for some laptop mice & trackballs.
  10  * 02Feb93  (troyer@saifr00.cfsat.Honeywell.COM,mch@wimsey.bc.ca)
  11  *
  12  * Changed to prevent keyboard lockups on AST Power Exec.
  13  * 28Jul93  Brad Bosch - brad@lachman.com
  14  *
  15  * Modified by Johan Myreen (jem@pandora.pp.fi) 04Aug93
  16  *   to include support for QuickPort mouse.
  17  *
  18  * Changed references to "QuickPort" with "82C710" since "QuickPort"
  19  * is not what this driver is all about -- QuickPort is just a
  20  * connector type, and this driver is for the mouse port on the Chips
  21  * & Technologies 82C710 interface chip. 15Nov93 jem@pandora.pp.fi
  22  *
  23  * Added support for SIGIO. 28Jul95 jem@pandora.pp.fi
  24  *
  25  * Rearranged SIGIO support to use code from tty_io.  9Sept95 ctm@ardi.com
  26  *
  27  * Modularised 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
  28  */
  29 
  30 /* Uncomment the following line if your mouse needs initialization. */
  31 
  32 /* #define INITIALIZE_DEVICE */
  33 
  34 #include <linux/module.h>
  35  
  36 #include <linux/sched.h>
  37 #include <linux/kernel.h>
  38 #include <linux/fcntl.h>
  39 #include <linux/errno.h>
  40 #include <linux/timer.h>
  41 #include <linux/malloc.h>
  42 #include <linux/mouse.h>
  43 #include <linux/random.h>
  44 
  45 #include <asm/io.h>
  46 #include <asm/segment.h>
  47 #include <asm/system.h>
  48 
  49 #include <linux/config.h>
  50 
  51 #define PSMOUSE_MINOR      1            /* minor device # for this mouse */
  52 
  53 /* aux controller ports */
  54 #define AUX_INPUT_PORT  0x60            /* Aux device output buffer */
  55 #define AUX_OUTPUT_PORT 0x60            /* Aux device input buffer */
  56 #define AUX_COMMAND     0x64            /* Aux device command buffer */
  57 #define AUX_STATUS      0x64            /* Aux device status reg */
  58 
  59 /* aux controller status bits */
  60 #define AUX_OBUF_FULL   0x21            /* output buffer (from device) full */
  61 #define AUX_IBUF_FULL   0x02            /* input buffer (to device) full */
  62 
  63 /* aux controller commands */
  64 #define AUX_CMD_WRITE   0x60            /* value to write to controller */
  65 #define AUX_MAGIC_WRITE 0xd4            /* value to send aux device data */
  66 
  67 #define AUX_INTS_ON     0x47            /* enable controller interrupts */
  68 #define AUX_INTS_OFF    0x65            /* disable controller interrupts */
  69 
  70 #define AUX_DISABLE     0xa7            /* disable aux */
  71 #define AUX_ENABLE      0xa8            /* enable aux */
  72 
  73 /* aux device commands */
  74 #define AUX_SET_RES     0xe8            /* set resolution */
  75 #define AUX_SET_SCALE11 0xe6            /* set 1:1 scaling */
  76 #define AUX_SET_SCALE21 0xe7            /* set 2:1 scaling */
  77 #define AUX_GET_SCALE   0xe9            /* get scaling factor */
  78 #define AUX_SET_STREAM  0xea            /* set stream mode */
  79 #define AUX_SET_SAMPLE  0xf3            /* set sample rate */
  80 #define AUX_ENABLE_DEV  0xf4            /* enable aux device */
  81 #define AUX_DISABLE_DEV 0xf5            /* disable aux device */
  82 #define AUX_RESET       0xff            /* reset aux device */
  83 
  84 #define MAX_RETRIES     60              /* some aux operations take long time*/
  85 #if defined(__alpha__) && !defined(CONFIG_PCI)
  86 # define AUX_IRQ        9               /* Jensen is odd indeed */
  87 #else
  88 # define AUX_IRQ        12
  89 #endif
  90 #define AUX_BUF_SIZE    2048
  91 
  92 /* 82C710 definitions */
  93 
  94 #define QP_DATA         0x310           /* Data Port I/O Address */
  95 #define QP_STATUS       0x311           /* Status Port I/O Address */
  96 
  97 #define QP_DEV_IDLE     0x01            /* Device Idle */
  98 #define QP_RX_FULL      0x02            /* Device Char received */
  99 #define QP_TX_IDLE      0x04            /* Device XMIT Idle */
 100 #define QP_RESET        0x08            /* Device Reset */
 101 #define QP_INTS_ON      0x10            /* Device Interrupt On */
 102 #define QP_ERROR_FLAG   0x20            /* Device Error */
 103 #define QP_CLEAR        0x40            /* Device Clear */
 104 #define QP_ENABLE       0x80            /* Device Enable */
 105 
 106 #define QP_IRQ          12
 107 
 108 extern unsigned char aux_device_present;
 109 extern unsigned char kbd_read_mask;     /* from keyboard.c */
 110 
 111 struct aux_queue {
 112         unsigned long head;
 113         unsigned long tail;
 114         struct wait_queue *proc_list;
 115         struct fasync_struct *fasync;
 116         unsigned char buf[AUX_BUF_SIZE];
 117 };
 118 
 119 static struct aux_queue *queue;
 120 static int aux_ready = 0;
 121 static int aux_count = 0;
 122 static int aux_present = 0;
 123 static int poll_aux_status(void);
 124 static int poll_aux_status_nosleep(void);
 125 static int fasync_aux(struct inode *inode, struct file *filp, int on);
 126 
 127 #ifdef CONFIG_82C710_MOUSE
 128 static int qp_present = 0;
 129 static int qp_count = 0;
 130 static int qp_data = QP_DATA;
 131 static int qp_status = QP_STATUS;
 132 
 133 static int poll_qp_status(void);
 134 static int probe_qp(void);
 135 #endif
 136 
 137 
 138 /*
 139  * Write to aux device
 140  */
 141 
 142 static void aux_write_dev(int val)
     /* [previous][next][first][last][top][bottom][index][help] */
 143 {
 144         poll_aux_status();
 145         outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);    /* write magic cookie */
 146         poll_aux_status();
 147         outb_p(val,AUX_OUTPUT_PORT);            /* write data */
 148 }
 149 
 150 /*
 151  * Write to device & handle returned ack
 152  */
 153 #if defined INITIALIZE_DEVICE
 154 static int aux_write_ack(int val)
     /* [previous][next][first][last][top][bottom][index][help] */
 155 {
 156         int retries = 0;
 157 
 158         poll_aux_status_nosleep();
 159         outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
 160         poll_aux_status_nosleep();
 161         outb_p(val,AUX_OUTPUT_PORT);
 162         poll_aux_status_nosleep();
 163 
 164         if ((inb(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
 165         {
 166                 return (inb(AUX_INPUT_PORT));
 167         }
 168         return 0;
 169 }
 170 #endif /* INITIALIZE_DEVICE */
 171 
 172 /*
 173  * Write aux device command
 174  */
 175 
 176 static void aux_write_cmd(int val)
     /* [previous][next][first][last][top][bottom][index][help] */
 177 {
 178         poll_aux_status();
 179         outb_p(AUX_CMD_WRITE,AUX_COMMAND);
 180         poll_aux_status();
 181         outb_p(val,AUX_OUTPUT_PORT);
 182 }
 183 
 184 
 185 static unsigned int get_from_queue(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 186 {
 187         unsigned int result;
 188         unsigned long flags;
 189 
 190         save_flags(flags);
 191         cli();
 192         result = queue->buf[queue->tail];
 193         queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
 194         restore_flags(flags);
 195         return result;
 196 }
 197 
 198 
 199 static inline int queue_empty(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 200 {
 201         return queue->head == queue->tail;
 202 }
 203 
 204 
 205 
 206 /*
 207  * Interrupt from the auxiliary device: a character
 208  * is waiting in the keyboard/aux controller.
 209  */
 210 
 211 static void aux_interrupt(int cpl, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 212 {
 213         int head = queue->head;
 214         int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
 215 
 216         if ((inb(AUX_STATUS) & AUX_OBUF_FULL) != AUX_OBUF_FULL)
 217                 return;
 218 
 219         add_mouse_randomness(queue->buf[head] = inb(AUX_INPUT_PORT));
 220         if (head != maxhead) {
 221                 head++;
 222                 head &= AUX_BUF_SIZE-1;
 223         }
 224         queue->head = head;
 225         aux_ready = 1;
 226         if (queue->fasync)
 227                 kill_fasync(queue->fasync, SIGIO);
 228         wake_up_interruptible(&queue->proc_list);
 229 }
 230 
 231 /*
 232  * Interrupt handler for the 82C710 mouse port. A character
 233  * is waiting in the 82C710.
 234  */
 235 
 236 #ifdef CONFIG_82C710_MOUSE
 237 static void qp_interrupt(int cpl, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 238 {
 239         int head = queue->head;
 240         int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
 241 
 242         add_mouse_randomness(queue->buf[head] = inb(qp_data));
 243         if (head != maxhead) {
 244                 head++;
 245                 head &= AUX_BUF_SIZE-1;
 246         }
 247         queue->head = head;
 248         aux_ready = 1;
 249         if (queue->fasync)
 250                 kill_fasync(queue->fasync, SIGIO);
 251         wake_up_interruptible(&queue->proc_list);
 252 }
 253 #endif
 254 
 255 
 256 static void release_aux(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 257 {
 258         fasync_aux(inode, file, 0);
 259         if (--aux_count)
 260                 return;
 261         aux_write_cmd(AUX_INTS_OFF);            /* disable controller ints */
 262         poll_aux_status();
 263         outb_p(AUX_DISABLE,AUX_COMMAND);        /* Disable Aux device */
 264         poll_aux_status();
 265         free_irq(AUX_IRQ);
 266         MOD_DEC_USE_COUNT;
 267 }
 268 
 269 #ifdef CONFIG_82C710_MOUSE
 270 static void release_qp(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 271 {
 272         unsigned char status;
 273 
 274         fasync_aux(inode, file, 0);
 275         if (--qp_count)
 276                 return;
 277         if (!poll_qp_status())
 278                 printk("Warning: Mouse device busy in release_qp()\n");
 279         status = inb_p(qp_status);
 280         outb_p(status & ~(QP_ENABLE|QP_INTS_ON), qp_status);
 281         if (!poll_qp_status())
 282                 printk("Warning: Mouse device busy in release_qp()\n");
 283         free_irq(QP_IRQ);
 284         MOD_DEC_USE_COUNT;
 285 }
 286 #endif
 287 
 288 static int fasync_aux(struct inode *inode, struct file *filp, int on)
     /* [previous][next][first][last][top][bottom][index][help] */
 289 {
 290         int retval;
 291 
 292         retval = fasync_helper(inode, filp, on, &queue->fasync);
 293         if (retval < 0)
 294                 return retval;
 295         return 0;
 296 }
 297 
 298 /*
 299  * Install interrupt handler.
 300  * Enable auxiliary device.
 301  */
 302 
 303 static int open_aux(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 304 {
 305         if (!aux_present)
 306                 return -ENODEV;
 307         if (aux_count++)
 308                 return 0;
 309         if (!poll_aux_status()) {
 310                 aux_count--;
 311                 return -EBUSY;
 312         }
 313         queue->head = queue->tail = 0;          /* Flush input queue */
 314         if (request_irq(AUX_IRQ, aux_interrupt, 0, "PS/2 Mouse")) {
 315                 aux_count--;
 316                 return -EBUSY;
 317         }
 318         poll_aux_status();
 319         outb_p(AUX_ENABLE,AUX_COMMAND);         /* Enable Aux */
 320         aux_write_dev(AUX_ENABLE_DEV);          /* enable aux device */
 321         aux_write_cmd(AUX_INTS_ON);             /* enable controller ints */
 322         poll_aux_status();
 323         aux_ready = 0;
 324         MOD_INC_USE_COUNT;
 325         return 0;
 326 }
 327 
 328 #ifdef CONFIG_82C710_MOUSE
 329 /*
 330  * Install interrupt handler.
 331  * Enable the device, enable interrupts. 
 332  */
 333 
 334 static int open_qp(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 335 {
 336         unsigned char status;
 337 
 338         if (!qp_present)
 339                 return -EINVAL;
 340 
 341         if (qp_count++)
 342                 return 0;
 343 
 344         if (request_irq(QP_IRQ, qp_interrupt, 0, "PS/2 Mouse")) {
 345                 qp_count--;
 346                 return -EBUSY;
 347         }
 348 
 349         status = inb_p(qp_status);
 350         status |= (QP_ENABLE|QP_RESET);
 351         outb_p(status, qp_status);
 352         status &= ~(QP_RESET);
 353         outb_p(status, qp_status);
 354 
 355         queue->head = queue->tail = 0;          /* Flush input queue */
 356         status |= QP_INTS_ON;
 357         outb_p(status, qp_status);              /* Enable interrupts */
 358 
 359         while (!poll_qp_status()) {
 360                 printk("Error: Mouse device busy in open_qp()\n");
 361                 qp_count--;
 362                 status &= ~(QP_ENABLE|QP_INTS_ON);
 363                 outb_p(status, qp_status);
 364                 free_irq(QP_IRQ);
 365                 return -EBUSY;
 366         }
 367 
 368         outb_p(AUX_ENABLE_DEV, qp_data);        /* Wake up mouse */
 369         MOD_INC_USE_COUNT;
 370         return 0;
 371 }
 372 #endif
 373 
 374 /*
 375  * Write to the aux device.
 376  */
 377 
 378 static int write_aux(struct inode * inode, struct file * file, const char * buffer, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 379 {
 380         int i = count;
 381 
 382         while (i--) {
 383                 if (!poll_aux_status())
 384                         return -EIO;
 385                 outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
 386                 if (!poll_aux_status())
 387                         return -EIO;
 388                 outb_p(get_user(buffer++),AUX_OUTPUT_PORT);
 389         }
 390         inode->i_mtime = CURRENT_TIME;
 391         return count;
 392 }
 393 
 394 
 395 #ifdef CONFIG_82C710_MOUSE
 396 /*
 397  * Write to the 82C710 mouse device.
 398  */
 399 
 400 static int write_qp(struct inode * inode, struct file * file, const char * buffer, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 401 {
 402         int i = count;
 403 
 404         while (i--) {
 405                 if (!poll_qp_status())
 406                         return -EIO;
 407                 outb_p(get_user(buffer++), qp_data);
 408         }
 409         inode->i_mtime = CURRENT_TIME;
 410         return count;
 411 }
 412 #endif
 413 
 414 
 415 /*
 416  * Put bytes from input queue to buffer.
 417  */
 418 
 419 static int read_aux(struct inode * inode, struct file * file, char * buffer, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 420 {
 421         struct wait_queue wait = { current, NULL };
 422         int i = count;
 423         unsigned char c;
 424 
 425         if (queue_empty()) {
 426                 if (file->f_flags & O_NONBLOCK)
 427                         return -EAGAIN;
 428                 add_wait_queue(&queue->proc_list, &wait);
 429 repeat:
 430                 current->state = TASK_INTERRUPTIBLE;
 431                 if (queue_empty() && !(current->signal & ~current->blocked)) {
 432                         schedule();
 433                         goto repeat;
 434                 }
 435                 current->state = TASK_RUNNING;
 436                 remove_wait_queue(&queue->proc_list, &wait);
 437         }
 438         while (i > 0 && !queue_empty()) {
 439                 c = get_from_queue();
 440                 put_user(c, buffer++);
 441                 i--;
 442         }
 443         aux_ready = !queue_empty();
 444         if (count-i) {
 445                 inode->i_atime = CURRENT_TIME;
 446                 return count-i;
 447         }
 448         if (current->signal & ~current->blocked)
 449                 return -ERESTARTSYS;
 450         return 0;
 451 }
 452 
 453 
 454 static int aux_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 455 {
 456         if (sel_type != SEL_IN)
 457                 return 0;
 458         if (aux_ready)
 459                 return 1;
 460         select_wait(&queue->proc_list, wait);
 461         return 0;
 462 }
 463 
 464 
 465 struct file_operations psaux_fops = {
 466         NULL,           /* seek */
 467         read_aux,
 468         write_aux,
 469         NULL,           /* readdir */
 470         aux_select,
 471         NULL,           /* ioctl */
 472         NULL,           /* mmap */
 473         open_aux,
 474         release_aux,
 475         NULL,
 476         fasync_aux,
 477 };
 478 
 479 
 480 /*
 481  * Initialize driver. First check for a 82C710 chip; if found
 482  * forget about the Aux port and use the *_qp functions.
 483  */
 484 static struct mouse psaux_mouse = {
 485         PSMOUSE_MINOR, "ps2aux", &psaux_fops
 486 };
 487 
 488 int psaux_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 489 {
 490         int qp_found = 0;
 491 
 492 #ifdef CONFIG_82C710_MOUSE
 493         if ((qp_found = probe_qp())) {
 494                 printk("82C710 type pointing device detected -- driver installed.\n");
 495 /*              printk("82C710 address = %x (should be 0x310)\n", qp_data); */
 496                 qp_present = 1;
 497                 psaux_fops.write = write_qp;
 498                 psaux_fops.open = open_qp;
 499                 psaux_fops.release = release_qp;
 500         } else
 501 #endif
 502         if (aux_device_present == 0xaa) {
 503                 printk("PS/2 auxiliary pointing device detected -- driver installed.\n");
 504                 aux_present = 1;
 505                 kbd_read_mask = AUX_OBUF_FULL;
 506         } else {
 507                 return -EIO;
 508         }
 509         mouse_register(&psaux_mouse);
 510         queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
 511         memset(queue, 0, sizeof(*queue));
 512         queue->head = queue->tail = 0;
 513         queue->proc_list = NULL;
 514         if (!qp_found) {
 515 #if defined INITIALIZE_DEVICE
 516                 outb_p(AUX_ENABLE,AUX_COMMAND);         /* Enable Aux */
 517                 aux_write_ack(AUX_SET_SAMPLE);
 518                 aux_write_ack(100);                     /* 100 samples/sec */
 519                 aux_write_ack(AUX_SET_RES);
 520                 aux_write_ack(3);                       /* 8 counts per mm */
 521                 aux_write_ack(AUX_SET_SCALE21);         /* 2:1 scaling */
 522                 poll_aux_status_nosleep();
 523 #endif /* INITIALIZE_DEVICE */
 524                 outb_p(AUX_DISABLE,AUX_COMMAND);   /* Disable Aux device */
 525                 poll_aux_status_nosleep();
 526                 outb_p(AUX_CMD_WRITE,AUX_COMMAND);
 527                 poll_aux_status_nosleep();             /* Disable interrupts */
 528                 outb_p(AUX_INTS_OFF, AUX_OUTPUT_PORT); /*  on the controller */
 529         }
 530         return 0;
 531 }
 532 
 533 #ifdef MODULE
 534 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 535 {
 536         return psaux_init(); /*?? Bjorn */
 537 }
 538 
 539 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 540 {
 541         mouse_deregister(&psaux_mouse);
 542 }
 543 #endif
 544 
 545 static int poll_aux_status(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 546 {
 547         int retries=0;
 548 
 549         while ((inb(AUX_STATUS)&0x03) && retries < MAX_RETRIES) {
 550                 if ((inb_p(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
 551                         inb_p(AUX_INPUT_PORT);
 552                 current->state = TASK_INTERRUPTIBLE;
 553                 current->timeout = jiffies + (5*HZ + 99) / 100;
 554                 schedule();
 555                 retries++;
 556         }
 557         return !(retries==MAX_RETRIES);
 558 }
 559 
 560 static int poll_aux_status_nosleep(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 561 {
 562         int retries = 0;
 563 
 564         while ((inb(AUX_STATUS)&0x03) && retries < 1000000) {
 565                 if ((inb_p(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
 566                         inb_p(AUX_INPUT_PORT);
 567                 retries++;
 568         }
 569         return !(retries == 1000000);
 570 }
 571 
 572 #ifdef CONFIG_82C710_MOUSE
 573 /*
 574  * Wait for device to send output char and flush any input char.
 575  */
 576 
 577 static int poll_qp_status(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 578 {
 579         int retries=0;
 580 
 581         while ((inb(qp_status)&(QP_RX_FULL|QP_TX_IDLE|QP_DEV_IDLE))
 582                        != (QP_DEV_IDLE|QP_TX_IDLE)
 583                        && retries < MAX_RETRIES) {
 584 
 585                 if (inb_p(qp_status)&(QP_RX_FULL))
 586                         inb_p(qp_data);
 587                 current->state = TASK_INTERRUPTIBLE;
 588                 current->timeout = jiffies + (5*HZ + 99) / 100;
 589                 schedule();
 590                 retries++;
 591         }
 592         return !(retries==MAX_RETRIES);
 593 }
 594 
 595 /*
 596  * Function to read register in 82C710.
 597  */
 598 
 599 static inline unsigned char read_710(unsigned char index)
     /* [previous][next][first][last][top][bottom][index][help] */
 600 {
 601         outb_p(index, 0x390);                   /* Write index */
 602         return inb_p(0x391);                    /* Read the data */
 603 }
 604 
 605 /*
 606  * See if we can find a 82C710 device. Read mouse address.
 607  */
 608 
 609 static int probe_qp(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 610 {
 611         outb_p(0x55, 0x2fa);                    /* Any value except 9, ff or 36 */
 612         outb_p(0xaa, 0x3fa);                    /* Inverse of 55 */
 613         outb_p(0x36, 0x3fa);                    /* Address the chip */
 614         outb_p(0xe4, 0x3fa);                    /* 390/4; 390 = config address */
 615         outb_p(0x1b, 0x2fa);                    /* Inverse of e4 */
 616         if (read_710(0x0f) != 0xe4)             /* Config address found? */
 617           return 0;                             /* No: no 82C710 here */
 618         qp_data = read_710(0x0d)*4;             /* Get mouse I/O address */
 619         qp_status = qp_data+1;
 620         outb_p(0x0f, 0x390);
 621         outb_p(0x0f, 0x391);                    /* Close config mode */
 622         return 1;
 623 }
 624 #endif

/* [previous][next][first][last][top][bottom][index][help] */