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

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