mse.c revision 47625
1/* 2 * Copyright 1992 by the University of Guelph 3 * 4 * Permission to use, copy and modify this 5 * software and its documentation for any purpose and without 6 * fee is hereby granted, provided that the above copyright 7 * notice appear in all copies and that both that copyright 8 * notice and this permission notice appear in supporting 9 * documentation. 10 * University of Guelph makes no representations about the suitability of 11 * this software for any purpose. It is provided "as is" 12 * without express or implied warranty. 13 * 14 * $Id: mse.c,v 1.42 1999/05/06 18:44:02 peter Exp $ 15 */ 16/* 17 * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and 18 * the X386 port, courtesy of 19 * Rick Macklem, rick@snowhite.cis.uoguelph.ca 20 * Caveats: The driver currently uses spltty(), but doesn't use any 21 * generic tty code. It could use splmse() (that only masks off the 22 * bus mouse interrupt, but that would require hacking in i386/isa/icu.s. 23 * (This may be worth the effort, since the Logitech generates 30/60 24 * interrupts/sec continuously while it is open.) 25 * NB: The ATI has NOT been tested yet! 26 */ 27 28/* 29 * Modification history: 30 * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com) 31 * improved probe based on input from Logitech. 32 * 33 * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu) 34 * fixes to make it work with Microsoft InPort busmouse 35 * 36 * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu) 37 * added patches for new "select" interface 38 * 39 * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu) 40 * changed position of some spl()'s in mseread 41 * 42 * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu) 43 * limit maximum negative x/y value to -127 to work around XFree problem 44 * that causes spurious button pushes. 45 */ 46 47#include "mse.h" 48#if NMSE > 0 49#include "opt_devfs.h" 50 51#include <sys/param.h> 52#include <sys/systm.h> 53#include <sys/conf.h> 54#include <sys/kernel.h> 55#include <sys/poll.h> 56#include <sys/select.h> 57#include <sys/uio.h> 58#ifdef DEVFS 59#include <sys/devfsext.h> 60#endif /*DEVFS*/ 61 62#include <machine/clock.h> 63#include <machine/mouse.h> 64 65#include <i386/isa/isa_device.h> 66 67/* driver configuration flags (config) */ 68#define MSE_CONFIG_ACCEL 0x00f0 /* acceleration factor */ 69#define MSE_CONFIG_FLAGS (MSE_CONFIG_ACCEL) 70 71static int mseprobe(struct isa_device *); 72static int mseattach(struct isa_device *); 73 74struct isa_driver msedriver = { 75 mseprobe, mseattach, "mse" 76}; 77 78static d_open_t mseopen; 79static d_close_t mseclose; 80static d_read_t mseread; 81static d_ioctl_t mseioctl; 82static d_poll_t msepoll; 83 84#define CDEV_MAJOR 27 85static struct cdevsw mse_cdevsw = { 86 /* open */ mseopen, 87 /* close */ mseclose, 88 /* read */ mseread, 89 /* write */ nowrite, 90 /* ioctl */ mseioctl, 91 /* stop */ nostop, 92 /* reset */ noreset, 93 /* devtotty */ nodevtotty, 94 /* poll */ msepoll, 95 /* mmap */ nommap, 96 /* strategy */ nostrategy, 97 /* name */ "mse", 98 /* parms */ noparms, 99 /* maj */ CDEV_MAJOR, 100 /* dump */ nodump, 101 /* psize */ nopsize, 102 /* flags */ 0, 103 /* maxio */ 0, 104 /* bmaj */ -1 105}; 106 107static ointhand2_t mseintr; 108 109/* 110 * Software control structure for mouse. The sc_enablemouse(), 111 * sc_disablemouse() and sc_getmouse() routines must be called spl'd(). 112 */ 113static struct mse_softc { 114 int sc_flags; 115 int sc_mousetype; 116 struct selinfo sc_selp; 117 u_int sc_port; 118 void (*sc_enablemouse) __P((u_int port)); 119 void (*sc_disablemouse) __P((u_int port)); 120 void (*sc_getmouse) __P((u_int port, int *dx, int *dy, int *but)); 121 int sc_deltax; 122 int sc_deltay; 123 int sc_obuttons; 124 int sc_buttons; 125 int sc_bytesread; 126 u_char sc_bytes[MOUSE_SYS_PACKETSIZE]; 127 mousehw_t hw; 128 mousemode_t mode; 129 mousestatus_t status; 130#ifdef DEVFS 131 void *devfs_token; 132 void *n_devfs_token; 133#endif 134} mse_sc[NMSE]; 135 136/* Flags */ 137#define MSESC_OPEN 0x1 138#define MSESC_WANT 0x2 139 140/* and Mouse Types */ 141#define MSE_NONE 0 /* don't move this! */ 142#define MSE_LOGITECH 0x1 143#define MSE_ATIINPORT 0x2 144#define MSE_LOGI_SIG 0xA5 145 146#define MSE_PORTA 0 147#define MSE_PORTB 1 148#define MSE_PORTC 2 149#define MSE_PORTD 3 150 151#define MSE_UNIT(dev) (minor(dev) >> 1) 152#define MSE_NBLOCKIO(dev) (minor(dev) & 0x1) 153 154/* 155 * Logitech bus mouse definitions 156 */ 157#define MSE_SETUP 0x91 /* What does this mean? */ 158 /* The definition for the control port */ 159 /* is as follows: */ 160 161 /* D7 = Mode set flag (1 = active) */ 162 /* D6,D5 = Mode selection (port A) */ 163 /* 00 = Mode 0 = Basic I/O */ 164 /* 01 = Mode 1 = Strobed I/O */ 165 /* 10 = Mode 2 = Bi-dir bus */ 166 /* D4 = Port A direction (1 = input)*/ 167 /* D3 = Port C (upper 4 bits) */ 168 /* direction. (1 = input) */ 169 /* D2 = Mode selection (port B & C) */ 170 /* 0 = Mode 0 = Basic I/O */ 171 /* 1 = Mode 1 = Strobed I/O */ 172 /* D1 = Port B direction (1 = input)*/ 173 /* D0 = Port C (lower 4 bits) */ 174 /* direction. (1 = input) */ 175 176 /* So 91 means Basic I/O on all 3 ports,*/ 177 /* Port A is an input port, B is an */ 178 /* output port, C is split with upper */ 179 /* 4 bits being an output port and lower*/ 180 /* 4 bits an input port, and enable the */ 181 /* sucker. */ 182 /* Courtesy Intel 8255 databook. Lars */ 183#define MSE_HOLD 0x80 184#define MSE_RXLOW 0x00 185#define MSE_RXHIGH 0x20 186#define MSE_RYLOW 0x40 187#define MSE_RYHIGH 0x60 188#define MSE_DISINTR 0x10 189#define MSE_INTREN 0x00 190 191static int mse_probelogi __P((struct isa_device *idp)); 192static void mse_disablelogi __P((u_int port)); 193static void mse_getlogi __P((u_int port, int *dx, int *dy, int *but)); 194static void mse_enablelogi __P((u_int port)); 195 196/* 197 * ATI Inport mouse definitions 198 */ 199#define MSE_INPORT_RESET 0x80 200#define MSE_INPORT_STATUS 0x00 201#define MSE_INPORT_DX 0x01 202#define MSE_INPORT_DY 0x02 203#define MSE_INPORT_MODE 0x07 204#define MSE_INPORT_HOLD 0x20 205#define MSE_INPORT_INTREN 0x09 206 207static int mse_probeati __P((struct isa_device *idp)); 208static void mse_enableati __P((u_int port)); 209static void mse_disableati __P((u_int port)); 210static void mse_getati __P((u_int port, int *dx, int *dy, int *but)); 211 212#define MSEPRI (PZERO + 3) 213 214/* 215 * Table of mouse types. 216 * Keep the Logitech last, since I haven't figured out how to probe it 217 * properly yet. (Someday I'll have the documentation.) 218 */ 219static struct mse_types { 220 int m_type; /* Type of bus mouse */ 221 int (*m_probe) __P((struct isa_device *idp)); 222 /* Probe routine to test for it */ 223 void (*m_enable) __P((u_int port)); 224 /* Start routine */ 225 void (*m_disable) __P((u_int port)); 226 /* Disable interrupts routine */ 227 void (*m_get) __P((u_int port, int *dx, int *dy, int *but)); 228 /* and get mouse status */ 229 mousehw_t m_hw; /* buttons iftype type model hwid */ 230 mousemode_t m_mode; /* proto rate res accel level size mask */ 231} mse_types[] = { 232 { MSE_ATIINPORT, 233 mse_probeati, mse_enableati, mse_disableati, mse_getati, 234 { 2, MOUSE_IF_INPORT, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, 235 { MOUSE_PROTO_INPORT, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 236 { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, 237 { MSE_LOGITECH, 238 mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi, 239 { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, 240 { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 241 { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, 242 { 0, }, 243}; 244 245int 246mseprobe(idp) 247 register struct isa_device *idp; 248{ 249 register struct mse_softc *sc = &mse_sc[idp->id_unit]; 250 register int i; 251 252 /* 253 * Check for each mouse type in the table. 254 */ 255 i = 0; 256 while (mse_types[i].m_type) { 257 if ((*mse_types[i].m_probe)(idp)) { 258 sc->sc_mousetype = mse_types[i].m_type; 259 sc->sc_enablemouse = mse_types[i].m_enable; 260 sc->sc_disablemouse = mse_types[i].m_disable; 261 sc->sc_getmouse = mse_types[i].m_get; 262 sc->hw = mse_types[i].m_hw; 263 sc->mode = mse_types[i].m_mode; 264 return (1); 265 } 266 i++; 267 } 268 return (0); 269} 270 271int 272mseattach(idp) 273 struct isa_device *idp; 274{ 275 int unit = idp->id_unit; 276 struct mse_softc *sc = &mse_sc[unit]; 277 278 idp->id_ointr = mseintr; 279 sc->sc_port = idp->id_iobase; 280 sc->mode.accelfactor = (idp->id_flags & MSE_CONFIG_ACCEL) >> 4; 281#ifdef DEVFS 282 sc->devfs_token = 283 devfs_add_devswf(&mse_cdevsw, unit << 1, DV_CHR, 0, 0, 284 0600, "mse%d", unit); 285 sc->n_devfs_token = 286 devfs_add_devswf(&mse_cdevsw, (unit<<1)+1, DV_CHR,0, 0, 287 0600, "nmse%d", unit); 288#endif 289 return (1); 290} 291 292/* 293 * Exclusive open the mouse, initialize it and enable interrupts. 294 */ 295static int 296mseopen(dev, flags, fmt, p) 297 dev_t dev; 298 int flags; 299 int fmt; 300 struct proc *p; 301{ 302 register struct mse_softc *sc; 303 int s; 304 305 if (MSE_UNIT(dev) >= NMSE) 306 return (ENXIO); 307 sc = &mse_sc[MSE_UNIT(dev)]; 308 if (sc->sc_mousetype == MSE_NONE) 309 return (ENXIO); 310 if (sc->sc_flags & MSESC_OPEN) 311 return (EBUSY); 312 sc->sc_flags |= MSESC_OPEN; 313 sc->sc_obuttons = sc->sc_buttons = MOUSE_MSC_BUTTONS; 314 sc->sc_deltax = sc->sc_deltay = 0; 315 sc->sc_bytesread = sc->mode.packetsize = MOUSE_MSC_PACKETSIZE; 316 sc->mode.level = 0; 317 sc->status.flags = 0; 318 sc->status.button = sc->status.obutton = 0; 319 sc->status.dx = sc->status.dy = sc->status.dz = 0; 320 321 /* 322 * Initialize mouse interface and enable interrupts. 323 */ 324 s = spltty(); 325 (*sc->sc_enablemouse)(sc->sc_port); 326 splx(s); 327 return (0); 328} 329 330/* 331 * mseclose: just turn off mouse innterrupts. 332 */ 333static int 334mseclose(dev, flags, fmt, p) 335 dev_t dev; 336 int flags; 337 int fmt; 338 struct proc *p; 339{ 340 struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 341 int s; 342 343 s = spltty(); 344 (*sc->sc_disablemouse)(sc->sc_port); 345 sc->sc_flags &= ~MSESC_OPEN; 346 splx(s); 347 return(0); 348} 349 350/* 351 * mseread: return mouse info using the MSC serial protocol, but without 352 * using bytes 4 and 5. 353 * (Yes this is cheesy, but it makes the X386 server happy, so...) 354 */ 355static int 356mseread(dev, uio, ioflag) 357 dev_t dev; 358 struct uio *uio; 359 int ioflag; 360{ 361 register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 362 int xfer, s, error; 363 364 /* 365 * If there are no protocol bytes to be read, set up a new protocol 366 * packet. 367 */ 368 s = spltty(); /* XXX Should be its own spl, but where is imlXX() */ 369 if (sc->sc_bytesread >= sc->mode.packetsize) { 370 while (sc->sc_deltax == 0 && sc->sc_deltay == 0 && 371 (sc->sc_obuttons ^ sc->sc_buttons) == 0) { 372 if (MSE_NBLOCKIO(dev)) { 373 splx(s); 374 return (0); 375 } 376 sc->sc_flags |= MSESC_WANT; 377 error = tsleep((caddr_t)sc, MSEPRI | PCATCH, 378 "mseread", 0); 379 if (error) { 380 splx(s); 381 return (error); 382 } 383 } 384 385 /* 386 * Generate protocol bytes. 387 * For some reason X386 expects 5 bytes but never uses 388 * the fourth or fifth? 389 */ 390 sc->sc_bytes[0] = sc->mode.syncmask[1] 391 | (sc->sc_buttons & ~sc->mode.syncmask[0]); 392 if (sc->sc_deltax > 127) 393 sc->sc_deltax = 127; 394 if (sc->sc_deltax < -127) 395 sc->sc_deltax = -127; 396 sc->sc_deltay = -sc->sc_deltay; /* Otherwise mousey goes wrong way */ 397 if (sc->sc_deltay > 127) 398 sc->sc_deltay = 127; 399 if (sc->sc_deltay < -127) 400 sc->sc_deltay = -127; 401 sc->sc_bytes[1] = sc->sc_deltax; 402 sc->sc_bytes[2] = sc->sc_deltay; 403 sc->sc_bytes[3] = sc->sc_bytes[4] = 0; 404 sc->sc_bytes[5] = sc->sc_bytes[6] = 0; 405 sc->sc_bytes[7] = MOUSE_SYS_EXTBUTTONS; 406 sc->sc_obuttons = sc->sc_buttons; 407 sc->sc_deltax = sc->sc_deltay = 0; 408 sc->sc_bytesread = 0; 409 } 410 splx(s); 411 xfer = min(uio->uio_resid, sc->mode.packetsize - sc->sc_bytesread); 412 error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio); 413 if (error) 414 return (error); 415 sc->sc_bytesread += xfer; 416 return(0); 417} 418 419/* 420 * mseioctl: process ioctl commands. 421 */ 422static int 423mseioctl(dev, cmd, addr, flag, p) 424 dev_t dev; 425 u_long cmd; 426 caddr_t addr; 427 int flag; 428 struct proc *p; 429{ 430 register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 431 mousestatus_t status; 432 int err = 0; 433 int s; 434 435 switch (cmd) { 436 437 case MOUSE_GETHWINFO: 438 s = spltty(); 439 *(mousehw_t *)addr = sc->hw; 440 if (sc->mode.level == 0) 441 ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC; 442 splx(s); 443 break; 444 445 case MOUSE_GETMODE: 446 s = spltty(); 447 *(mousemode_t *)addr = sc->mode; 448 switch (sc->mode.level) { 449 case 0: 450 break; 451 case 1: 452 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE; 453 ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK; 454 ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC; 455 break; 456 } 457 splx(s); 458 break; 459 460 case MOUSE_SETMODE: 461 switch (((mousemode_t *)addr)->level) { 462 case 0: 463 case 1: 464 break; 465 default: 466 return (EINVAL); 467 } 468 if (((mousemode_t *)addr)->accelfactor < -1) 469 return (EINVAL); 470 else if (((mousemode_t *)addr)->accelfactor >= 0) 471 sc->mode.accelfactor = 472 ((mousemode_t *)addr)->accelfactor; 473 sc->mode.level = ((mousemode_t *)addr)->level; 474 switch (sc->mode.level) { 475 case 0: 476 sc->sc_bytesread = sc->mode.packetsize 477 = MOUSE_MSC_PACKETSIZE; 478 break; 479 case 1: 480 sc->sc_bytesread = sc->mode.packetsize 481 = MOUSE_SYS_PACKETSIZE; 482 break; 483 } 484 break; 485 486 case MOUSE_GETLEVEL: 487 *(int *)addr = sc->mode.level; 488 break; 489 490 case MOUSE_SETLEVEL: 491 switch (*(int *)addr) { 492 case 0: 493 sc->mode.level = *(int *)addr; 494 sc->sc_bytesread = sc->mode.packetsize 495 = MOUSE_MSC_PACKETSIZE; 496 break; 497 case 1: 498 sc->mode.level = *(int *)addr; 499 sc->sc_bytesread = sc->mode.packetsize 500 = MOUSE_SYS_PACKETSIZE; 501 break; 502 default: 503 return (EINVAL); 504 } 505 break; 506 507 case MOUSE_GETSTATUS: 508 s = spltty(); 509 status = sc->status; 510 sc->status.flags = 0; 511 sc->status.obutton = sc->status.button; 512 sc->status.button = 0; 513 sc->status.dx = 0; 514 sc->status.dy = 0; 515 sc->status.dz = 0; 516 splx(s); 517 *(mousestatus_t *)addr = status; 518 break; 519 520 case MOUSE_READSTATE: 521 case MOUSE_READDATA: 522 return (ENODEV); 523 524#if (defined(MOUSE_GETVARS)) 525 case MOUSE_GETVARS: 526 case MOUSE_SETVARS: 527 return (ENODEV); 528#endif 529 530 default: 531 return (ENOTTY); 532 } 533 return (err); 534} 535 536/* 537 * msepoll: check for mouse input to be processed. 538 */ 539static int 540msepoll(dev, events, p) 541 dev_t dev; 542 int events; 543 struct proc *p; 544{ 545 register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 546 int s; 547 int revents = 0; 548 549 s = spltty(); 550 if (events & (POLLIN | POLLRDNORM)) { 551 if (sc->sc_bytesread != sc->mode.packetsize || 552 sc->sc_deltax != 0 || sc->sc_deltay != 0 || 553 (sc->sc_obuttons ^ sc->sc_buttons) != 0) 554 revents |= events & (POLLIN | POLLRDNORM); 555 else { 556 /* 557 * Since this is an exclusive open device, any previous 558 * proc pointer is trash now, so we can just assign it. 559 */ 560 selrecord(p, &sc->sc_selp); 561 } 562 } 563 splx(s); 564 return (revents); 565} 566 567/* 568 * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative. 569 */ 570static void 571mseintr(unit) 572 int unit; 573{ 574 /* 575 * the table to turn MouseSystem button bits (MOUSE_MSC_BUTTON?UP) 576 * into `mousestatus' button bits (MOUSE_BUTTON?DOWN). 577 */ 578 static int butmap[8] = { 579 0, 580 MOUSE_BUTTON3DOWN, 581 MOUSE_BUTTON2DOWN, 582 MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN, 583 MOUSE_BUTTON1DOWN, 584 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 585 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN, 586 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN 587 }; 588 register struct mse_softc *sc = &mse_sc[unit]; 589 int dx, dy, but; 590 int sign; 591 592#ifdef DEBUG 593 static int mse_intrcnt = 0; 594 if((mse_intrcnt++ % 10000) == 0) 595 printf("mseintr\n"); 596#endif /* DEBUG */ 597 if ((sc->sc_flags & MSESC_OPEN) == 0) 598 return; 599 600 (*sc->sc_getmouse)(sc->sc_port, &dx, &dy, &but); 601 if (sc->mode.accelfactor > 0) { 602 sign = (dx < 0); 603 dx = dx * dx / sc->mode.accelfactor; 604 if (dx == 0) 605 dx = 1; 606 if (sign) 607 dx = -dx; 608 sign = (dy < 0); 609 dy = dy * dy / sc->mode.accelfactor; 610 if (dy == 0) 611 dy = 1; 612 if (sign) 613 dy = -dy; 614 } 615 sc->sc_deltax += dx; 616 sc->sc_deltay += dy; 617 sc->sc_buttons = but; 618 619 but = butmap[~but & MOUSE_MSC_BUTTONS]; 620 sc->status.dx += dx; 621 sc->status.dy += dy; 622 sc->status.flags |= ((dx || dy) ? MOUSE_POSCHANGED : 0) 623 | (sc->status.button ^ but); 624 sc->status.button = but; 625 626 /* 627 * If mouse state has changed, wake up anyone wanting to know. 628 */ 629 if (sc->sc_deltax != 0 || sc->sc_deltay != 0 || 630 (sc->sc_obuttons ^ sc->sc_buttons) != 0) { 631 if (sc->sc_flags & MSESC_WANT) { 632 sc->sc_flags &= ~MSESC_WANT; 633 wakeup((caddr_t)sc); 634 } 635 selwakeup(&sc->sc_selp); 636 } 637} 638 639/* 640 * Routines for the Logitech mouse. 641 */ 642/* 643 * Test for a Logitech bus mouse and return 1 if it is. 644 * (until I know how to use the signature port properly, just disable 645 * interrupts and return 1) 646 */ 647static int 648mse_probelogi(idp) 649 register struct isa_device *idp; 650{ 651 652 int sig; 653 654 outb(idp->id_iobase + MSE_PORTD, MSE_SETUP); 655 /* set the signature port */ 656 outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG); 657 658 DELAY(30000); /* 30 ms delay */ 659 sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF; 660 if (sig == MSE_LOGI_SIG) { 661 outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR); 662 return(1); 663 } else { 664 if (bootverbose) 665 printf("mse%d: wrong signature %x\n",idp->id_unit,sig); 666 return(0); 667 } 668} 669 670/* 671 * Initialize Logitech mouse and enable interrupts. 672 */ 673static void 674mse_enablelogi(port) 675 register u_int port; 676{ 677 int dx, dy, but; 678 679 outb(port + MSE_PORTD, MSE_SETUP); 680 mse_getlogi(port, &dx, &dy, &but); 681} 682 683/* 684 * Disable interrupts for Logitech mouse. 685 */ 686static void 687mse_disablelogi(port) 688 register u_int port; 689{ 690 691 outb(port + MSE_PORTC, MSE_DISINTR); 692} 693 694/* 695 * Get the current dx, dy and button up/down state. 696 */ 697static void 698mse_getlogi(port, dx, dy, but) 699 register u_int port; 700 int *dx; 701 int *dy; 702 int *but; 703{ 704 register char x, y; 705 706 outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW); 707 x = inb(port + MSE_PORTA); 708 *but = (x >> 5) & MOUSE_MSC_BUTTONS; 709 x &= 0xf; 710 outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH); 711 x |= (inb(port + MSE_PORTA) << 4); 712 outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW); 713 y = (inb(port + MSE_PORTA) & 0xf); 714 outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH); 715 y |= (inb(port + MSE_PORTA) << 4); 716 *dx = x; 717 *dy = y; 718 outb(port + MSE_PORTC, MSE_INTREN); 719} 720 721/* 722 * Routines for the ATI Inport bus mouse. 723 */ 724/* 725 * Test for a ATI Inport bus mouse and return 1 if it is. 726 * (do not enable interrupts) 727 */ 728static int 729mse_probeati(idp) 730 register struct isa_device *idp; 731{ 732 int i; 733 734 for (i = 0; i < 2; i++) 735 if (inb(idp->id_iobase + MSE_PORTC) == 0xde) 736 return (1); 737 return (0); 738} 739 740/* 741 * Initialize ATI Inport mouse and enable interrupts. 742 */ 743static void 744mse_enableati(port) 745 register u_int port; 746{ 747 748 outb(port + MSE_PORTA, MSE_INPORT_RESET); 749 outb(port + MSE_PORTA, MSE_INPORT_MODE); 750 outb(port + MSE_PORTB, MSE_INPORT_INTREN); 751} 752 753/* 754 * Disable interrupts for ATI Inport mouse. 755 */ 756static void 757mse_disableati(port) 758 register u_int port; 759{ 760 761 outb(port + MSE_PORTA, MSE_INPORT_MODE); 762 outb(port + MSE_PORTB, 0); 763} 764 765/* 766 * Get current dx, dy and up/down button state. 767 */ 768static void 769mse_getati(port, dx, dy, but) 770 register u_int port; 771 int *dx; 772 int *dy; 773 int *but; 774{ 775 register char byte; 776 777 outb(port + MSE_PORTA, MSE_INPORT_MODE); 778 outb(port + MSE_PORTB, MSE_INPORT_HOLD); 779 outb(port + MSE_PORTA, MSE_INPORT_STATUS); 780 *but = ~inb(port + MSE_PORTB) & MOUSE_MSC_BUTTONS; 781 outb(port + MSE_PORTA, MSE_INPORT_DX); 782 byte = inb(port + MSE_PORTB); 783 *dx = byte; 784 outb(port + MSE_PORTA, MSE_INPORT_DY); 785 byte = inb(port + MSE_PORTB); 786 *dy = byte; 787 outb(port + MSE_PORTA, MSE_INPORT_MODE); 788 outb(port + MSE_PORTB, MSE_INPORT_INTREN); 789} 790 791static int mse_devsw_installed; 792 793static void mse_drvinit(void *unused) 794{ 795 dev_t dev; 796 797 if( ! mse_devsw_installed ) { 798 dev = makedev(CDEV_MAJOR, 0); 799 cdevsw_add(&dev,&mse_cdevsw, NULL); 800 mse_devsw_installed = 1; 801 } 802} 803 804SYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL) 805 806 807#endif /* NMSE */ 808