00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00037 #include <ipc/irc.h>
00038 #include <async.h>
00039 #include <sysinfo.h>
00040 #include <kbd.h>
00041 #include <kbd_port.h>
00042 #include <sun.h>
00043 #include <ddi.h>
00044 #include <errno.h>
00045
00046
00047 #define RBR_REG 0
00048 #define IER_REG 1
00049 #define IIR_REG 2
00050 #define FCR_REG 2
00051 #define LCR_REG 3
00052 #define MCR_REG 4
00053 #define LSR_REG 5
00055 #define LSR_DATA_READY 0x01
00056
00057 static irq_cmd_t ns16550_cmds[] = {
00058 {
00059 .cmd = CMD_PIO_READ_8,
00060 .addr = (void *) 0,
00061 .dstarg = 1
00062 },
00063 {
00064 .cmd = CMD_BTEST,
00065 .value = LSR_DATA_READY,
00066 .srcarg = 1,
00067 .dstarg = 3
00068 },
00069 {
00070 .cmd = CMD_PREDICATE,
00071 .value = 2,
00072 .srcarg = 3
00073 },
00074 {
00075 .cmd = CMD_PIO_READ_8,
00076 .addr = (void *) 0,
00077 .dstarg = 2
00078 },
00079 {
00080 .cmd = CMD_ACCEPT
00081 }
00082 };
00083
00084 irq_code_t ns16550_kbd = {
00085 sizeof(ns16550_cmds) / sizeof(irq_cmd_t),
00086 ns16550_cmds
00087 };
00088
00089 static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call);
00090
00091 static uintptr_t ns16550_physical;
00092 static uintptr_t ns16550_kernel;
00093
00094 int ns16550_port_init(void)
00095 {
00096 void *vaddr;
00097
00098 if (sysinfo_get_value("kbd.address.physical", &ns16550_physical) != EOK)
00099 return -1;
00100
00101 if (sysinfo_get_value("kbd.address.kernel", &ns16550_kernel) != EOK)
00102 return -1;
00103
00104 sysarg_t inr;
00105 if (sysinfo_get_value("kbd.inr", &inr) != EOK)
00106 return -1;
00107
00108 ns16550_kbd.cmds[0].addr = (void *) (ns16550_kernel + LSR_REG);
00109 ns16550_kbd.cmds[3].addr = (void *) (ns16550_kernel + RBR_REG);
00110
00111 async_set_interrupt_received(ns16550_irq_handler);
00112 register_irq(inr, device_assign_devno(), inr, &ns16550_kbd);
00113
00114 return pio_enable((void *) ns16550_physical, 8, &vaddr);
00115 }
00116
00117 static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call)
00118 {
00119 int scan_code = IPC_GET_ARG2(*call);
00120 kbd_push_scancode(scan_code);
00121
00122 if (irc_service)
00123 async_msg_1(irc_phone, IRC_CLEAR_INTERRUPT,
00124 IPC_GET_IMETHOD(*call));
00125 }
00126