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