1 /* 2 * Copyright (c) 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. 7 * 8 * %sccs.include.redist.c% 9 * 10 * from: $Hdr: ms.c,v 4.300 91/06/09 06:22:04 root Rel41 $ SONY 11 * 12 * @(#)ms.c 7.1 (Berkeley) 06/04/92 13 */ 14 15 #include "../include/fix_machine_type.h" 16 17 #include "ms.h" 18 #if NMS > 0 19 /* 20 * mouse 21 */ 22 23 #include "types.h" 24 #include "../include/cpu.h" 25 #include "../include/pte.h" 26 #include "param.h" 27 #include "proc.h" 28 #include "user.h" 29 #include "buf.h" 30 #include "malloc.h" 31 #include "systm.h" 32 #include "uio.h" 33 #include "kernel.h" 34 #include "file.h" 35 36 #include "../iop/mouse.h" 37 #include "../iop/msreg.h" 38 39 #include "../sio/scc.h" 40 #include "../hbdev/hbvar.h" 41 42 #ifndef mips 43 #define volatile 44 #endif /* mips */ 45 46 struct ms_stat ms_stat[NMS]; 47 48 int msprobe(), msattach(); 49 50 struct hb_device *msinfo[NMS]; 51 struct hb_driver msdriver = { 52 msprobe, 0, msattach, 0, 0, "ms", msinfo, "mc", 0, 0 53 }; 54 55 #ifndef news700 56 extern int tty00_is_console; 57 #endif 58 59 #ifdef news3400 60 #define splms spl4 61 #else /* news3400 */ 62 #ifdef news700 63 #define splms spl4 64 #else /* news700 */ 65 #define splms spl5 66 #endif /* news700 */ 67 #endif /* news3400 */ 68 69 /*ARGSUSED*/ 70 msprobe(ii) 71 struct hb_device *ii; 72 { 73 return(sizeof(struct ms_stat)); 74 } 75 76 /*ARGSUSED*/ 77 msattach(ii) 78 struct hb_device *ii; 79 { 80 81 } 82 83 /* queue structure operators */ 84 85 msq_init(unit) 86 int unit; 87 { 88 register volatile struct ms_queue *q = ms_stat[unit].mss_queue; 89 90 q->mq_head = q->mq_tail = 0; 91 } 92 93 int 94 msq_stat(unit) 95 int unit; 96 { 97 register volatile struct ms_queue *q = ms_stat[unit].mss_queue; 98 99 while (q->mq_head != q->mq_tail) { 100 if (!q->mq_queue[q->mq_head].mse_inval) 101 break; 102 q->mq_head = ++q->mq_head % MS_MAXREPORT; 103 } 104 return (q->mq_head != q->mq_tail); 105 } 106 107 struct ms_event * 108 msq_read(unit) 109 int unit; 110 { 111 register volatile struct ms_queue *q = ms_stat[unit].mss_queue; 112 register volatile struct ms_event *data; 113 114 while (q->mq_head != q->mq_tail && q->mq_queue[q->mq_head].mse_inval) 115 q->mq_head = ++q->mq_head % MS_MAXREPORT; 116 if (q->mq_head == q->mq_tail) { 117 data = NULL; 118 } else { 119 data = q->mq_queue + q->mq_head++; 120 q->mq_head %= MS_MAXREPORT; 121 } 122 return (data); 123 } 124 125 struct ms_event * 126 msq_write(unit) 127 int unit; 128 { 129 register volatile struct ms_queue *q = ms_stat[unit].mss_queue; 130 register volatile struct ms_event *data = q->mq_queue + q->mq_tail; 131 register int new; 132 133 /* if queue is full, newest data is gone away */ 134 new = (q->mq_tail + 1) % MS_MAXREPORT; 135 if (new != q->mq_head) 136 q->mq_tail = new; 137 return (data); 138 } 139 140 msq_flush(unit, trig) 141 int unit; 142 char trig; 143 { 144 register volatile struct ms_queue *q = ms_stat[unit].mss_queue; 145 register int i; 146 147 i = q->mq_head; 148 while (i != q->mq_tail) { 149 if (q->mq_queue[i].mse_trig == trig) 150 q->mq_queue[i].mse_inval = -1; 151 i = ++i % MS_MAXREPORT; 152 } 153 } 154 155 /* 156 * Mouse open function. 157 */ 158 msopen(dev, flag) 159 dev_t dev; 160 int flag; 161 { 162 register int unit = MSUNIT(dev); 163 register struct ms_stat *ms = &ms_stat[unit]; 164 register struct hb_device *ii = msinfo[unit]; 165 static struct ms_coord initxy = { 0, 0 }; 166 167 /* check device */ 168 if (unit < 0 || unit >= NMS || ii == NULL || ii->hi_alive == 0) 169 return(ENXIO); 170 171 /* check duplicable open */ 172 if (ms->mss_stat & MS_ACTIVE) 173 return(EBUSY); 174 175 ms->mss_queue = malloc(sizeof(struct ms_queue), M_DEVBUF, M_WAITOK); 176 if (ms->mss_queue == NULL) 177 return (ENOMEM); 178 msq_init(unit); 179 ms->mss_mode = flag; 180 ms->mss_stat = MS_ACTIVE; 181 182 /* communicate to IOP .. clear event mask, set initial xy. */ 183 ms->mss_eventmask = 0; 184 ms->mss_data.md_sw = 0; /* XXX */ 185 ms->mss_data.md_x = 0; 186 ms->mss_data.md_y = 0; 187 ms->mss_param.mp_delta = 5; 188 ms->mss_param.mp_mag = 3; 189 ms->mss_range.mr_min.mc_x = 0x80000000; 190 ms->mss_range.mr_min.mc_y = 0x80000000; 191 ms->mss_range.mr_max.mc_x = 0x7fffffff; 192 ms->mss_range.mr_max.mc_y = 0x7fffffff; 193 194 if (curproc->p_pgrp->pg_id == 0) { 195 if (ms->mss_pgrp == 0) 196 ms->mss_pgrp = curproc->p_pid; 197 curproc->p_pgrp->pg_id = ms->mss_pgrp; 198 } 199 #ifdef news700 200 scc_open(SCC_MOUSE); 201 #else 202 if (tty00_is_console) 203 kbm_open(SCC_KEYBOARD); 204 kbm_open(SCC_MOUSE); 205 #endif 206 207 return (0); 208 } 209 210 /* 211 * Mouse close function. 212 */ 213 214 /*ARGSUSED*/ 215 msclose(dev, flag) 216 dev_t dev; 217 int flag; 218 { 219 int unit = MSUNIT(dev); 220 register struct ms_stat *ms = &ms_stat[unit]; 221 register struct hb_device *ii = msinfo[unit]; 222 223 /* check unit no. */ 224 if (unit < 0 || unit >= NMS || ii == NULL || ii->hi_alive == 0) 225 return ENXIO; 226 227 /* check status */ 228 if (!(ms->mss_stat & MS_ACTIVE)) 229 return ENXIO; 230 231 /* clear eventmask and status */ 232 ms->mss_stat = 0; 233 ms->mss_eventmask = 0; 234 235 free(ms->mss_queue, M_DEVBUF); 236 ms->mss_pgrp = 0; 237 #ifndef news700 238 if (tty00_is_console) 239 kbm_close(SCC_KEYBOARD); 240 kbm_close(SCC_MOUSE); 241 #endif /* news700 */ 242 243 return (0); 244 } 245 246 /* 247 * Mouse read function. 248 */ 249 250 msread(dev, uio, flag) 251 dev_t dev; 252 struct uio *uio; 253 int flag; 254 { 255 register int unit = MSUNIT(dev); 256 register struct ms_stat *ms = &ms_stat[unit]; 257 register struct hb_device *ii = msinfo[unit]; 258 register volatile struct ms_event *data; 259 struct ms_data xy; 260 int s, error; 261 262 /* check argument */ 263 if (unit < 0 || unit >= NMS || ii == NULL || ii->hi_alive == 0) 264 return ENXIO; 265 266 /* event mode -> waiting */ 267 if (ms->mss_eventmask & MS_EMEVENT) { 268 s = splms(); 269 if (msq_stat(unit) == 0 && (ms->mss_stat & MS_NBIO)) { 270 splx(s); 271 return (EWOULDBLOCK); 272 } 273 while (msq_stat(unit) == 0) { 274 ms->mss_stat |= MS_EVWAIT; 275 sleep((caddr_t)&ms->mss_queue, MSPRI); 276 ms->mss_stat &= ~MS_EVWAIT; 277 } 278 splx(s); 279 if(MSOLDIF(dev)) { 280 while ((data = msq_read(unit)) != NULL && 281 uio->uio_resid >= sizeof(struct ms_data)) { 282 error = uiomove((caddr_t)&data->mse_data, 283 sizeof(struct ms_data), uio); 284 if (error) 285 return error; 286 } 287 } else { 288 while ((data = msq_read(unit)) != NULL && 289 uio->uio_resid >= sizeof(struct ms_event)) { 290 error = uiomove((caddr_t)data, 291 sizeof(struct ms_event), uio); 292 if (error) 293 return error; 294 } 295 } 296 } else { 297 while (uio->uio_resid >= sizeof(struct ms_data)) { 298 s = splms(); 299 xy = ms->mss_data; 300 splx(s); 301 error = uiomove((caddr_t)&xy, 302 sizeof(struct ms_data), uio); 303 if (error) 304 return error; 305 } 306 } 307 return 0; 308 } 309 310 /* 311 * Mouse write function 312 */ 313 314 mswrite(dev, uio, flag) 315 dev_t dev; 316 struct uio *uio; 317 int flag; 318 { 319 register int unit = MSUNIT(dev); 320 register struct ms_stat *ms = &ms_stat[unit]; 321 register struct hb_device *ii = msinfo[unit]; 322 struct ms_coord xy; 323 register int s, error; 324 325 /* check argument */ 326 if (unit < 0 || unit >= NMS || ii == NULL || ii->hi_alive == 0) 327 return ENXIO; 328 329 while (uio->uio_resid >= sizeof(struct ms_coord)) { 330 error = uiomove((caddr_t)&xy, sizeof(xy), uio); 331 if (error) 332 return error; 333 s = splms(); 334 ms->mss_data.md_x = xy.mc_x; 335 ms->mss_data.md_y = xy.mc_y; 336 splx(s); 337 lock_bitmap(); 338 updateCursor(&ms->mss_data.md_x, &ms->mss_data.md_y, 1); 339 unlock_bitmap(); 340 } 341 return 0; 342 } 343 344 345 /* 346 * Mouse I/O control function 347 */ 348 349 /*ARGSUSED*/ 350 msioctl(dev, cmd, data, flag) 351 dev_t dev; 352 int cmd; 353 caddr_t data; 354 int flag; 355 { 356 register int unit = MSUNIT(dev); 357 register struct ms_stat *ms = &ms_stat[unit]; 358 register struct hb_device *ii = msinfo[unit]; 359 register int s; 360 361 if (unit < 0 || unit >= NMS || ii == NULL || ii->hi_alive == 0) 362 return EIO; 363 364 s = splms(); 365 366 switch (cmd) { 367 case MSIOCGETEM: 368 (*(int*)data) = ms->mss_eventmask; 369 break; 370 case MSIOCSETEM: 371 ms->mss_eventmask = *(int *)data; 372 break; 373 case MSIOCSETXY: 374 ms->mss_data.md_x = ((struct ms_coord*)data)->mc_x; 375 ms->mss_data.md_y = ((struct ms_coord*)data)->mc_y; 376 lock_bitmap(); 377 updateCursor(&ms->mss_data.md_x, &ms->mss_data.md_y, 1); 378 unlock_bitmap(); 379 msq_flush(unit, MSE_MOTION); 380 break; 381 case MSIOCFLUSH: 382 msq_init(unit); 383 break; 384 case MSIOCSETPARAM: 385 ms->mss_param = *(struct ms_param*)data; 386 break; 387 case MSIOCSETRANGE: 388 ms->mss_range = *(struct ms_range*)data; 389 break; 390 case FIONBIO: 391 if (*(int *)data) 392 ms->mss_stat |= MS_NBIO; 393 else 394 ms->mss_stat &= ~MS_NBIO; 395 break; 396 case FIOASYNC: 397 if (*(int *)data) 398 ms->mss_stat |= MS_ASYNC; 399 else 400 ms->mss_stat &= ~MS_ASYNC; 401 break; 402 case TIOCSPGRP: 403 ms->mss_pgrp = *(int *)data; 404 break; 405 case TIOCGPGRP: 406 *(int *)data = ms->mss_pgrp; 407 break; 408 default: 409 splx(s); 410 return ENOTTY; 411 } 412 splx(s); 413 return 0; 414 } 415 416 msselect(dev, flag) 417 dev_t dev; 418 int flag; 419 { 420 register int unit = MSUNIT(dev); 421 register struct ms_stat *ms; 422 int s; 423 424 if (unit < 0 || unit >= NMS) 425 return(0); 426 427 s = splms(); 428 ms = &ms_stat[unit]; 429 430 switch(flag) { 431 case FREAD: 432 if (!(ms->mss_eventmask & MS_EMEVENT)) 433 goto win; 434 if(msq_stat(unit)) 435 goto win; 436 437 if (ms->mss_rsel && ms->mss_rsel->p_wchan == (caddr_t)&selwait) 438 ms->mss_stat |= MS_RCOLL; 439 else 440 ms->mss_rsel = curproc; 441 break; 442 443 case FWRITE: 444 goto win; 445 } 446 splx(s); 447 return(0); 448 win: 449 splx(s); 450 return(1); 451 } 452 453 msselwakeup(ms) 454 register struct ms_stat *ms; 455 { 456 if (ms->mss_rsel) { 457 selwakeup(ms->mss_rsel, ms->mss_stat&MS_RCOLL); 458 ms->mss_stat &= ~MS_RCOLL; 459 ms->mss_rsel = 0; 460 } 461 if (ms->mss_stat & MS_ASYNC) 462 gsignal(ms->mss_pgrp, SIGIO); 463 } 464 465 mssint() 466 { 467 printf("mssint\n"); 468 } 469 470 msputevent(unit, trig, dir, code) 471 int unit, trig, dir, code; 472 { 473 register struct ms_stat *ms = &ms_stat[unit]; 474 register volatile struct ms_event *me; 475 register int s; 476 477 me = msq_write(unit); 478 479 s = splclock(); 480 me->mse_time = time; 481 me->mse_inval = 0; 482 splx(s); 483 484 me->mse_trig = trig; 485 me->mse_dir = dir; 486 me->mse_code = code; 487 me->mse_data = ms->mss_data; 488 489 if (ms->mss_stat & MS_EVWAIT) 490 wakeup((caddr_t)&ms->mss_queue); 491 492 msselwakeup(ms); 493 494 return (0); 495 } 496 497 /* 498 * for keyboard 499 */ 500 mskeytrigger(unit, up, keycode) 501 int unit; 502 int up; 503 int keycode; 504 { 505 register struct ms_stat *ms = &ms_stat[unit]; 506 507 if((ms->mss_eventmask & MS_EMEVENT) == 0) 508 return 0; 509 if((ms->mss_eventmask & MS_EMKEY) == 0) 510 return 0; 511 512 (void) msputevent(unit, MSE_KEY, up ? MSE_UP : MSE_DOWN, keycode); 513 514 return 1; 515 } 516 517 /* 518 * msconv - convert mouse hardware reports(3 bytes) into internal mouse data 519 * it leaves the old mouse data in ms_data_old and 520 * new mouse data in ms_data. 521 */ 522 msconv(unit, rep) 523 int unit; 524 register char rep[]; 525 { 526 register struct ms_stat *ms = &ms_stat[unit]; 527 register int s_byte; 528 register int sw = 0; 529 register int dx, dy; 530 int adx, ady; 531 532 ms->mss_data_old = ms->mss_data; 533 534 /* switch status */ 535 s_byte = rep[MS_S_BYTE]; 536 if (s_byte & MS_S_SW1) 537 sw |= MS_BUTNL; 538 if (s_byte & MS_S_SW2) 539 sw |= MS_BUTNR; 540 if (s_byte & MS_S_SW3) 541 sw |= MS_BUTNM; 542 ms->mss_data.md_sw = sw; 543 544 /* delta x */ 545 dx = rep[MS_X_BYTE] & MS_X_X06; 546 if (s_byte & MS_S_X7) 547 dx = (~0&~MS_X_X06)|dx; 548 549 dy = rep[MS_Y_BYTE] & MS_Y_Y06; 550 if (s_byte & MS_S_Y7) 551 dy = (~0&~MS_Y_Y06)|dy; 552 553 #define ABS(x) ((x)>=0 ? (x) : -(x)) 554 adx = ABS(dx); 555 ady = ABS(dy); 556 #undef ABS 557 558 if (adx > ms->mss_param.mp_delta) { 559 adx = ms->mss_param.mp_delta + 560 (adx - ms->mss_param.mp_delta) * ms->mss_param.mp_mag; 561 if (dx < 0) 562 dx = -adx; 563 else 564 dx = adx; 565 } 566 if (ady > ms->mss_param.mp_delta) { 567 ady = ms->mss_param.mp_delta + 568 (ady - ms->mss_param.mp_delta) * ms->mss_param.mp_mag; 569 if (dy < 0) 570 dy = -ady; 571 else 572 dy = ady; 573 } 574 ms->mss_data.md_x += dx; 575 ms->mss_data.md_y += dy; 576 577 if (dx > 0) 578 ms->mss_data.md_x = MIN(ms->mss_data.md_x, 579 ms->mss_range.mr_max.mc_x); 580 else 581 ms->mss_data.md_x = MAX(ms->mss_data.md_x, 582 ms->mss_range.mr_min.mc_x); 583 if (dy > 0) 584 ms->mss_data.md_y = MIN(ms->mss_data.md_y, 585 ms->mss_range.mr_max.mc_y); 586 else 587 ms->mss_data.md_y = MAX(ms->mss_data.md_y, 588 ms->mss_range.mr_min.mc_y); 589 590 if (dx != 0 || dy != 0) 591 updateCursor(&ms->mss_data.md_x, &ms->mss_data.md_y, 0); 592 } 593 594 mscheckevent(unit) 595 int unit; 596 { 597 register struct ms_stat *ms = &ms_stat[unit]; 598 register int i; 599 register int changebits; 600 register int dir; 601 602 if ((ms->mss_eventmask & MS_EMEVENT) == 0) 603 return; 604 605 if (ms->mss_data_old.md_sw != ms->mss_data.md_sw) { 606 607 changebits = (ms->mss_data_old.md_sw ^ ms->mss_data.md_sw); 608 changebits &= ms->mss_eventmask; 609 610 for(i = 0; i < 3; i++) { 611 if(changebits & (1 << i)) { 612 if((1 << i) & ms->mss_data.md_sw) 613 dir = MSE_DOWN; 614 else 615 dir = MSE_UP; 616 msputevent(unit, MSE_BUTTON, dir, i); 617 } 618 } 619 } 620 621 if ((ms->mss_eventmask & MS_EMMOTION) && 622 (ms->mss_data_old.md_x != ms->mss_data.md_x || 623 ms->mss_data_old.md_y != ms->mss_data.md_y)) { 624 msputevent(unit, MSE_MOTION, 0, 0); 625 return; 626 } 627 } 628 629 /* 630 * _ms_helper - open the mouse line and read mouse data and 631 * convert them into mouse data (events) 632 */ 633 _ms_helper(unit) 634 int unit; 635 { 636 register int c; 637 static int counter = 0; 638 static char buf[MS_DB_SIZE]; 639 640 #ifdef notyet /* KU:XXX */ 641 intrcnt[INTR_MOUSE]++; 642 #endif 643 644 #if NBM > 0 645 rst_dimmer_cnt(); 646 #endif 647 648 while ((c = xgetc(SCC_MOUSE)) >= 0) { 649 if (c & MS_S_MARK) 650 counter = 0; 651 buf[counter] = c; 652 if (++counter == 3) { 653 msconv(unit, buf); 654 mscheckevent(unit); 655 counter = 0; 656 } 657 } 658 } 659 #endif /* NMS > 0 */ 660