psm.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 2,239 行 · 第 1/5 页
C
2,239 行
if (verbose >= 2) log(LOG_DEBUG, "psm: SET_STREAM_MODE return code:%04x\n", res); return (res == PSM_ACK);}#endif /* PSM_RESETAFTERSUSPEND */static intget_mouse_buttons(KBDC kbdc){ int c = 2; /* assume two buttons by default */ int status[3]; /* * NOTE: a special sequence to obtain Logitech Mouse specific * information: set resolution to 25 ppi, set scaling to 1:1, set * scaling to 1:1, set scaling to 1:1. Then the second byte of the * mouse status bytes is the number of available buttons. * Some manufactures also support this sequence. */ if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW) return c; if (set_mouse_scaling(kbdc, 1) && set_mouse_scaling(kbdc, 1) && set_mouse_scaling(kbdc, 1) && (get_mouse_status(kbdc, status, 0, 3) >= 3)) { if (status[1] != 0) return status[1]; } return c;}/* misc subroutines *//* * Someday, I will get the complete list of valid pointing devices and * their IDs... XXX */static intis_a_mouse(int id){#if 0 static int valid_ids[] = { PSM_MOUSE_ID, /* mouse */ PSM_BALLPOINT_ID, /* ballpoint device */ PSM_INTELLI_ID, /* Intellimouse */ -1 /* end of table */ }; int i; for (i = 0; valid_ids[i] >= 0; ++i) if (valid_ids[i] == id) return TRUE; return FALSE;#else return TRUE;#endif}static char *model_name(int model){ static struct { int model_code; char *model_name; } models[] = { { MOUSE_MODEL_NETSCROLL, "NetScroll Mouse" }, { MOUSE_MODEL_NET, "NetMouse" }, { MOUSE_MODEL_GLIDEPOINT, "GlidePoint" }, { MOUSE_MODEL_THINK, "ThinkingMouse" }, { MOUSE_MODEL_INTELLI, "IntelliMouse" }, { MOUSE_MODEL_MOUSEMANPLUS, "MouseMan+" }, { MOUSE_MODEL_GENERIC, "Generic PS/2 mouse" }, { MOUSE_MODEL_UNKNOWN, NULL }, }; int i; for (i = 0; models[i].model_code != MOUSE_MODEL_UNKNOWN; ++i) { if (models[i].model_code == model) return models[i].model_name; } return "Unknown";}static voidrecover_from_error(KBDC kbdc){ /* discard anything left in the output buffer */ empty_both_buffers(kbdc, 10);#if 0 /* * NOTE: KBDC_RESET_KBD may not restore the communication between the * keyboard and the controller. */ reset_kbd(kbdc);#else /* * NOTE: somehow diagnostic and keyboard port test commands bring the * keyboard back. */ if (!test_controller(kbdc)) log(LOG_ERR, "psm: keyboard controller failed.\n"); /* if there isn't a keyboard in the system, the following error is OK */ if (test_kbd_port(kbdc) != 0) { if (verbose) log(LOG_ERR, "psm: keyboard port failed.\n"); }#endif}static intrestore_controller(KBDC kbdc, int command_byte){ empty_both_buffers(kbdc, 10); if (!set_controller_command_byte(kbdc, 0xff, command_byte)) { log(LOG_ERR, "psm: failed to restore the keyboard controller " "command byte.\n"); return FALSE; } else { return TRUE; }}#ifdef PSM_RESETAFTERSUSPEND/* * Re-initialize the aux port and device. The aux port must be enabled * and its interrupt must be disabled before calling this routine. * The aux device will be disabled before returning. * The keyboard controller must be locked via `kbdc_lock()' before * calling this routine. */static intreinitialize(int unit, mousemode_t *mode){ struct psm_softc *sc = psm_softc[unit]; KBDC kbdc = psm_softc[unit]->kbdc; int stat[3]; int i; switch((i = test_aux_port(kbdc))) { case 1: /* ignore this error */ case PSM_ACK: if (verbose) log(LOG_DEBUG, "psm%d: strange result for test aux port (%d).\n", unit, i); /* fall though */ case 0: /* no error */ break; case -1: /* time out */ default: /* error */ recover_from_error(kbdc); if (sc->config & PSM_CONFIG_IGNPORTERROR) break; log(LOG_ERR, "psm%d: the aux port is not functioning (%d).\n", unit, i); return FALSE; } if (sc->config & PSM_CONFIG_NORESET) { /* * Don't try to reset the pointing device. It may possibly be * left in the unknown state, though... */ } else { /* * NOTE: some controllers appears to hang the `keyboard' when * the aux port doesn't exist and `PSMC_RESET_DEV' is issued. */ if (!reset_aux_dev(kbdc)) { recover_from_error(kbdc); log(LOG_ERR, "psm%d: failed to reset the aux device.\n", unit); return FALSE; } } /* * both the aux port and the aux device is functioning, see * if the device can be enabled. */ if (!enable_aux_dev(kbdc) || !disable_aux_dev(kbdc)) { log(LOG_ERR, "psm%d: failed to enable the aux device.\n", unit); return FALSE; } empty_both_buffers(kbdc, 10); /* remove stray data if any */ if (sc->config & PSM_CONFIG_NOIDPROBE) { i = GENERIC_MOUSE_ENTRY; } else { /* FIXME: hardware ID, mouse buttons? */ /* other parameters */ for (i = 0; vendortype[i].probefunc != NULL; ++i) { if ((*vendortype[i].probefunc)(sc)) { if (verbose >= 2) log(LOG_ERR, "psm%d: found %s\n", unit, model_name(vendortype[i].model)); break; } } } sc->hw.model = vendortype[i].model; sc->mode.packetsize = vendortype[i].packetsize; /* set mouse parameters */ if (mode != (mousemode_t *)NULL) { if (mode->rate > 0) mode->rate = set_mouse_sampling_rate(kbdc, mode->rate); if (mode->resolution >= 0) mode->resolution = set_mouse_resolution(kbdc, mode->resolution); set_mouse_scaling(kbdc, 1); set_mouse_mode(kbdc); } /* request a data packet and extract sync. bits */ if (get_mouse_status(kbdc, stat, 1, 3) < 3) { log(LOG_DEBUG, "psm%d: failed to get data (reinitialize).\n", unit); sc->mode.syncmask[0] = 0; } else { sc->mode.syncmask[1] = stat[0] & sc->mode.syncmask[0]; /* syncbits */ /* the NetScroll Mouse will send three more bytes... Ignore them */ empty_aux_buffer(kbdc, 5); } /* just check the status of the mouse */ if (get_mouse_status(kbdc, stat, 0, 3) < 3) log(LOG_DEBUG, "psm%d: failed to get status (reinitialize).\n", unit); return TRUE;}#endif /* PSM_RESETAFTERSUSPEND */static intdoopen(int unit, int command_byte){ struct psm_softc *sc = psm_softc[unit]; int stat[3]; /* enable the mouse device */ if (!enable_aux_dev(sc->kbdc)) { /* MOUSE ERROR: failed to enable the mouse because: * 1) the mouse is faulty, * 2) the mouse has been removed(!?) * In the latter case, the keyboard may have hung, and need * recovery procedure... */ recover_from_error(sc->kbdc);#if 0 /* FIXME: we could reset the mouse here and try to enable * it again. But it will take long time and it's not a good * idea to disable the keyboard that long... */ if (!reinitialize(unit, &sc->mode) || !enable_aux_dev(sc->kbdc)) { recover_from_error(sc->kbdc);#else {#endif restore_controller(sc->kbdc, command_byte); /* mark this device is no longer available */ sc->state &= ~PSM_VALID; log(LOG_ERR, "psm%d: failed to enable the device (doopen).\n", unit); return (EIO); } } if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3) log(LOG_DEBUG, "psm%d: failed to get status (doopen).\n", unit); /* enable the aux port and interrupt */ if (!set_controller_command_byte(sc->kbdc, kbdc_get_device_mask(sc->kbdc), (command_byte & KBD_KBD_CONTROL_BITS) | KBD_ENABLE_AUX_PORT | KBD_ENABLE_AUX_INT)) { /* CONTROLLER ERROR */ disable_aux_dev(sc->kbdc); restore_controller(sc->kbdc, command_byte); log(LOG_ERR, "psm%d: failed to enable the aux interrupt (doopen).\n", unit); return (EIO); } return (0);}/* psm driver entry points */#define endprobe(v) { if (bootverbose) \ --verbose; \ kbdc_set_device_mask(sc->kbdc, mask); \ kbdc_lock(sc->kbdc, FALSE); \ free(sc, M_DEVBUF); \ return (v); \ }static intpsmprobe(struct isa_device *dvp){ int unit = dvp->id_unit; struct psm_softc *sc; int stat[3]; int command_byte; int mask; int i; /* validate unit number */ if (unit >= NPSM) return (0); psm_softc[unit] = NULL; sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT); if (sc == NULL) return (0); bzero(sc, sizeof *sc);#if 0 kbdc_debug(TRUE);#endif sc->addr = dvp->id_iobase; sc->kbdc = kbdc_open(sc->addr); sc->config = dvp->id_flags & PSM_CONFIG_FLAGS; sc->flags = 0; if (bootverbose) ++verbose; if (!kbdc_lock(sc->kbdc, TRUE)) { printf("psm%d: unable to lock the controller.\n", unit); if (bootverbose) --verbose; free(sc, M_DEVBUF); return (0); } /* * NOTE: two bits in the command byte controls the operation of the * aux port (mouse port): the aux port disable bit (bit 5) and the aux * port interrupt (IRQ 12) enable bit (bit 2). */ /* discard anything left after the keyboard initialization */ empty_both_buffers(sc->kbdc, 10); /* save the current command byte; it will be used later */ mask = kbdc_get_device_mask(sc->kbdc) & ~KBD_AUX_CONTROL_BITS; command_byte = get_controller_command_byte(sc->kbdc); if (verbose) printf("psm%d: current command byte:%04x\n", unit, command_byte); if (command_byte == -1) { /* CONTROLLER ERROR */ printf("psm%d: unable to get the current command byte value.\n", unit); endprobe(0); } /* * disable the keyboard port while probing the aux port, which must be * enabled during this routine */ if (!set_controller_command_byte(sc->kbdc, KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS, KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { /* * this is CONTROLLER ERROR; I don't know how to recover * from this error... */ restore_controller(sc->kbdc, command_byte); printf("psm%d: unable to set the command byte.\n", unit); endprobe(0); } write_controller_command(sc->kbdc, KBDC_ENABLE_AUX_PORT); /* * NOTE: `test_aux_port()' is designed to return with zero if the aux * port exists and is functioning. However, some controllers appears * to respond with zero even when the aux port doesn't exist. (It may * be that this is only the case when the controller DOES have the aux * port but the port is not wired on the motherboard.) The keyboard * controllers without the port, such as the original AT, are * supporsed to return with an error code or simply time out. In any * case, we have to continue probing the port even when the controller * passes this test. * * XXX: some controllers erroneously return the error code 1 when * it has the perfectly functional aux port. We have to ignore this * error code. Even if the controller HAS error with the aux port, * it will be detected later... * XXX: another incompatible controller returns PSM_ACK (0xfa)... */ switch ((i = test_aux_port(sc->kbdc))) { case 1: /* ignore this error */ case PSM_ACK: if (verbose) printf("psm%d: strange result for test aux port (%d).\n", unit, i); /* fall though */ case 0: /* no error */ break; case -1: /* time out */ default: /* error */ recover_from_error(sc->kbdc); if (sc->config & PSM_CONFIG_IGNPORTERROR) break; restore_controller(sc->kbdc, command_byte); if (verbose) printf("psm%d: the aux port is not functioning (%d).\n", unit, i); endprobe(0); } if (sc->config & PSM_CONFIG_NORESET) { /* * Don't try to reset the pointing device. It may possibly be * left in the unknown state, though... */ } else { /* * NOTE: some controllers appears to hang the `keyboard' when the aux * port doesn't exist and `PSMC_RESET_DEV' is issued. */ if (!reset_aux_dev(sc->kbdc)) { recover_from_error(sc->kbdc); restore_controller(sc->kbdc, command_byte); if (verbose) printf("psm%d: failed to reset the aux device.\n", unit); endprobe(0); } } /* * both the aux port and the aux device is functioning, see if the * device can be enabled. NOTE: when enabled, the device will start * sending data; we shall immediately disable the device once we know * the device can be enabled. */ if (!enable_aux_dev(sc->kbdc) || !disable_aux_dev(sc->kbdc)) { /* MOUSE ERROR */ recover_from_error(sc->kbdc); restore_controller(sc->kbdc, command_byte); if (verbose) printf("psm%d: failed to enable the aux device.\n", unit); endprobe(0); } /* save the default values after reset */ if (get_mouse_status(sc->kbdc, stat, 0, 3) >= 3) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?