Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / acorn26 / ioc / arckbd.c
blobb90592e33d00b9ca55fc8cbcfc089165f4e6ea9f
1 /* $NetBSD: arckbd.c,v 1.17 2009/02/14 10:20:55 bjh21 Exp $ */
2 /*-
3 * Copyright (c) 1998, 1999, 2000 Ben Harris
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * arckbd.c - Archimedes keyboard driver
33 * Most of the information used to write this driver came from the
34 * A3000 Technical Reference Manual (ISBN 1-85250-074-3).
36 * We keep a queue of one command in the softc for use by the receive
37 * interrupt handler in case it finds the KART is already transmitting
38 * a command (presumably as a consequence of a user request) when it
39 * wants to. I think this is safe in all cases, and it will never
40 * happen more than once at a time (I hope).
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: arckbd.c,v 1.17 2009/02/14 10:20:55 bjh21 Exp $");
46 #include <sys/param.h>
47 #include <sys/device.h>
48 #include <sys/errno.h>
49 #include <sys/ioctl.h>
50 #include <sys/malloc.h>
51 #include <sys/proc.h>
52 #include <sys/reboot.h> /* For bootverbose */
53 #include <sys/syslog.h>
54 #include <sys/systm.h>
56 #include <machine/bus.h>
57 #include <machine/intr.h>
58 #include <machine/irq.h>
60 #include <dev/wscons/wsconsio.h>
61 #include <dev/wscons/wskbdvar.h>
62 #include <dev/wscons/wsksymdef.h>
63 #include <dev/wscons/wsmousevar.h>
65 #include <arch/acorn26/iobus/iocreg.h>
66 #include <arch/acorn26/iobus/iocvar.h>
67 #include <arch/acorn26/ioc/arckbdreg.h>
68 #include <arch/acorn26/ioc/arckbdvar.h>
70 #include "wskbd.h"
71 #include "wsmouse.h"
73 #include "rnd.h"
74 #if NRND > 0
75 #include <sys/rnd.h>
76 #endif
78 /* #define ARCKBD_DEBUG */
80 enum arckbd_state {
81 AS_HRST, AS_RAK1, AS_RAK2, /* reset protocol */
82 AS_IDLE, /* idle, waiting for data */
83 AS_KDDA, AS_KUDA, AS_MDAT /* Receiving two-byte message */
86 static const char *arckbd_statenames[] = {
87 "hrst", "rak1", "rak2", "idle", "kdda", "kuda", "mdat"
90 static int arckbd_match(device_t parent, cfdata_t cf, void *aux);
91 static void arckbd_attach(device_t parent, device_t self, void *aux);
92 #if 0 /* XXX should be used */
93 static kbd_t arckbd_pick_layout(int kbid);
94 #endif
96 static int arckbd_rint(void *self);
97 static int arckbd_xint(void *self);
98 static void arckbd_mousemoved(device_t self, int byte1, int byte2);
99 static void arckbd_keyupdown(device_t self, int byte1, int byte2);
100 static int arckbd_send(device_t self, int data,
101 enum arckbd_state newstate, int waitok);
103 static int arckbd_enable(void *cookie, int on);
104 static int arckbd_led_encode(int);
105 static int arckbd_led_decode(int);
106 static void arckbd_set_leds(void *cookie, int new_state);
107 static int arckbd_ioctl(void *cookie, u_long cmd, void *data, int flag,
108 struct lwp *l);
109 #if NWSKBD > 0
110 static void arckbd_getc(void *cookie, u_int *typep, int *valuep);
111 static void arckbd_pollc(void *cookie, int poll);
112 #endif
114 static int arcmouse_enable(void *cookie);
115 static int arcmouse_ioctl(void *cookie, u_long cmd, void *data, int flag,
116 struct lwp *l);
117 static void arcmouse_disable(void *cookie);
119 struct arckbd_softc {
120 device_t sc_dev;
121 bus_space_tag_t sc_bst;
122 bus_space_handle_t sc_bsh;
123 u_int sc_mouse_buttons;
124 enum arckbd_state sc_state;
125 u_char sc_byteone;
126 u_char sc_kbid;
127 struct device *sc_wskbddev;
128 struct device *sc_wsmousedev;
129 struct wskbd_mapdata sc_mapdata;
130 int sc_cmdqueue; /* Single-command queue */
131 enum arckbd_state sc_statequeue;
132 int sc_cmdqueued;
133 int sc_flags;
134 int sc_leds;
135 u_int sc_poll_type;
136 int sc_poll_value;
137 struct irq_handler *sc_xirq;
138 struct evcnt sc_xev;
139 struct irq_handler *sc_rirq;
140 struct evcnt sc_rev;
141 #if NRND > 0
142 rndsource_element_t sc_rnd_source;
143 #endif
146 #define AKF_WANTKBD 0x01
147 #define AKF_WANTMOUSE 0x02
148 #define AKF_SENTRQID 0x04
149 #define AKF_SENTLEDS 0x08
150 #define AKF_POLLING 0x10
152 CFATTACH_DECL_NEW(arckbd, sizeof(struct arckbd_softc),
153 arckbd_match, arckbd_attach, NULL, NULL);
155 static struct wskbd_accessops arckbd_accessops = {
156 arckbd_enable, arckbd_set_leds, arckbd_ioctl
159 #if NWSKBD > 0
160 static struct wskbd_consops arckbd_consops = {
161 arckbd_getc, arckbd_pollc
163 #endif
165 static struct wsmouse_accessops arcmouse_accessops = {
166 arcmouse_enable, arcmouse_ioctl, arcmouse_disable
169 /* ARGSUSED */
170 static int
171 arckbd_match(device_t parent, cfdata_t cf, void *aux)
174 /* Assume presence for now */
175 return 1;
178 static void
179 arckbd_attach(device_t parent, device_t self, void *aux)
181 struct arckbd_softc *sc = device_private(self);
182 struct ioc_attach_args *ioc = aux;
183 bus_space_tag_t bst;
184 bus_space_handle_t bsh;
185 struct wskbddev_attach_args wskbdargs;
186 struct wsmousedev_attach_args wsmouseargs;
188 bst = sc->sc_bst = ioc->ioc_fast_t;
189 bsh = sc->sc_bsh = ioc->ioc_fast_h;
191 sc->sc_dev = self;
192 evcnt_attach_dynamic(&sc->sc_rev, EVCNT_TYPE_INTR, NULL,
193 device_xname(sc->sc_dev), "rx intr");
194 sc->sc_rirq = irq_establish(IOC_IRQ_SRX, IPL_TTY, arckbd_rint, self,
195 &sc->sc_rev);
196 aprint_verbose("\n%s: interrupting at %s (rx)", device_xname(self),
197 irq_string(sc->sc_rirq));
199 evcnt_attach_dynamic(&sc->sc_xev, EVCNT_TYPE_INTR, NULL,
200 device_xname(sc->sc_dev), "tx intr");
201 sc->sc_xirq = irq_establish(IOC_IRQ_STX, IPL_TTY, arckbd_xint, self,
202 &sc->sc_xev);
203 irq_disable(sc->sc_xirq);
204 aprint_verbose(" and %s (tx)", irq_string(sc->sc_xirq));
206 /* Initialisation of IOC KART per IOC Data Sheet section 6.2.3. */
208 /* Set up IOC counter 3 */
209 /* k_BAUD = 1/((latch+1)*16) MHz */
210 ioc_counter_start(parent, 3, 62500 / ARCKBD_BAUD - 1);
212 /* Read from Rx register and discard. */
213 (void)bus_space_read_1(bst, bsh, 0);
215 /* Kick the keyboard into life */
216 arckbd_send(self, ARCKBD_HRST, AS_HRST, 0);
218 sc->sc_mapdata = arckbd_mapdata_default;
219 sc->sc_mapdata.layout = KB_UK; /* Reasonable default */
221 /* Attach the wskbd console */
222 arckbd_cnattach(self);
224 aprint_normal("\n");
226 #if NRND > 0
227 rnd_attach_source(&sc->sc_rnd_source, device_xname(self),
228 RND_TYPE_TTY, 0);
229 #endif
231 wskbdargs.console = 1; /* XXX FIXME */
232 wskbdargs.keymap = &sc->sc_mapdata;
233 wskbdargs.accessops = &arckbd_accessops;
234 wskbdargs.accesscookie = sc;
235 sc->sc_wskbddev = config_found_ia(self, "wskbddev", &wskbdargs, NULL);
237 wsmouseargs.accessops = &arcmouse_accessops;
238 wsmouseargs.accesscookie = sc;
239 sc->sc_wsmousedev =
240 config_found_ia(self, "wsmousedev", &wsmouseargs, NULL);
243 #if 0 /* XXX should be used */
244 static kbd_t
245 arckbd_pick_layout(int kbid)
247 int i;
249 for (i = 0; arckbd_kbidtab[i].kbid != 0; i++) {
250 if (arckbd_kbidtab[i].kbid == kbid)
251 return arckbd_kbidtab[i].layout;
253 return KB_UK;
255 #endif
258 * We don't really _need_ a console keyboard before
259 * autoconfiguration's finished, so for now this function's written to
260 * be called from arckbd_attach. The console functions should still
261 * try not to rely on much, and perhaps one day we should make it
262 * happen in consinit instead.
265 void
266 arckbd_cnattach(device_t self)
268 #if NWSKBD > 0
269 struct arckbd_softc *sc = device_private(self);
271 wskbd_cnattach(&arckbd_consops, sc, &arckbd_mapdata_default);
272 #endif
275 #if NWSKBD > 0
276 static void
277 arckbd_getc(void *cookie, u_int *typep, int *valuep)
279 struct arckbd_softc *sc = cookie;
280 int s;
282 if (!(sc->sc_flags & AKF_POLLING))
283 panic("%s: arckbd_getc called with polling disabled",
284 device_xname(sc->sc_dev));
285 while (sc->sc_poll_type == 0) {
286 if (ioc_irq_status(IOC_IRQ_STX))
287 arckbd_xint(sc->sc_dev);
288 if (ioc_irq_status(IOC_IRQ_SRX))
289 arckbd_rint(sc->sc_dev);
291 s = spltty();
292 *typep = sc->sc_poll_type;
293 *valuep = sc->sc_poll_value;
294 sc->sc_poll_type = 0;
295 sc->sc_poll_value = 0;
296 splx(s);
299 static void
300 arckbd_pollc(void *cookie, int poll)
302 struct arckbd_softc *sc = cookie;
303 int s;
305 s = spltty();
306 if (poll) {
307 sc->sc_flags |= AKF_POLLING;
308 irq_disable(sc->sc_rirq);
309 irq_disable(sc->sc_xirq);
310 } else {
311 sc->sc_flags &= ~AKF_POLLING;
312 irq_enable(sc->sc_rirq);
313 irq_enable(sc->sc_xirq);
315 splx(s);
317 #endif
319 static int
320 arckbd_send(device_t self, int data, enum arckbd_state newstate, int waitok)
322 struct arckbd_softc *sc = device_private(self);
323 int s, res;
324 bus_space_tag_t bst = sc->sc_bst;
325 bus_space_handle_t bsh = sc->sc_bsh;
327 s = spltty();
328 if (waitok) {
329 while (!ioc_irq_status(IOC_IRQ_STX))
330 if ((sc->sc_flags & AKF_POLLING) == 0) {
331 res = tsleep(arckbd_send, PWAIT, "kbdsend", 0);
332 if (res != 0)
333 return res;
335 } else if (!ioc_irq_status(IOC_IRQ_STX)) {
336 if (sc->sc_cmdqueued)
337 panic("%s: queue overflow", device_xname(sc->sc_dev));
338 else {
339 sc->sc_cmdqueue = data;
340 sc->sc_statequeue = newstate;
341 sc->sc_cmdqueued = 1;
342 return 0;
345 bus_space_write_1(bst, bsh, 0, data);
346 sc->sc_state = newstate;
347 #ifdef ARCKBD_DEBUG
348 log(LOG_DEBUG, "%s: sent 0x%02x. now in state %s\n",
349 device_xname(sc->sc_dev), data, arckbd_statenames[newstate]);
350 #endif
351 wakeup(&sc->sc_state);
352 splx(s);
353 if ((sc->sc_flags & AKF_POLLING) == 0)
354 irq_enable(sc->sc_xirq);
355 return 0;
358 static int
359 arckbd_xint(void *cookie)
361 struct arckbd_softc *sc = device_private(cookie);
363 irq_disable(sc->sc_xirq);
364 /* First, process queued commands (acks from the last receive) */
365 if (sc->sc_cmdqueued) {
366 sc->sc_cmdqueued = 0;
367 arckbd_send(sc->sc_dev, sc->sc_cmdqueue, sc->sc_statequeue, 0);
368 } else if (sc->sc_state == AS_IDLE) {
369 /* Do things that need doing after a reset */
370 if (!(sc->sc_flags & AKF_SENTRQID)) {
371 arckbd_send(sc->sc_dev, ARCKBD_RQID, AS_IDLE, 0);
372 sc->sc_flags |= AKF_SENTRQID;
373 } else if (!(sc->sc_flags & AKF_SENTLEDS)) {
374 arckbd_send(sc->sc_dev, ARCKBD_LEDS | sc->sc_leds,
375 AS_IDLE, 0);
376 sc->sc_flags |= AKF_SENTLEDS;
378 } else if ((sc->sc_flags & AKF_POLLING) == 0)
379 wakeup(&arckbd_send);
380 return IRQ_HANDLED;
383 static int
384 arckbd_rint(void *cookie)
386 device_t self = cookie;
387 struct arckbd_softc *sc = device_private(self);
388 bus_space_tag_t bst = sc->sc_bst;
389 bus_space_handle_t bsh = sc->sc_bsh;
390 int data;
392 data = bus_space_read_1(bst, bsh, 0);
393 #ifdef ARCKBD_DEBUG
394 log(LOG_DEBUG, "%s: got 0x%02x in state %s\n", device_xname(self), data,
395 arckbd_statenames[sc->sc_state]);
396 #endif
397 /* Reset protocol */
398 if (data == ARCKBD_HRST && sc->sc_state == AS_HRST)
399 arckbd_send(self, ARCKBD_RAK1, AS_RAK1, 0);
400 else if (data == ARCKBD_RAK1 &&
401 (sc->sc_state == AS_RAK1 || sc->sc_state == AS_HRST))
402 arckbd_send(self, ARCKBD_RAK2, AS_RAK2, 0);
403 else if (data == ARCKBD_RAK2 && sc->sc_state == AS_RAK2)
404 arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0);
407 * Note that for data messages, we acknowledge first and
408 * _then_ process the data. This is important because the
409 * processing may end up trying to use the keyboard in polled
410 * mode (e.g. through DDB) and we'd like its state to be
411 * self-consistent.
414 /* Mouse data */
415 else if (ARCKBD_IS_MDAT(data) && sc->sc_state == AS_IDLE) {
416 arckbd_send(self, ARCKBD_BACK, AS_MDAT, 0);
417 sc->sc_byteone = data;
418 } else if (ARCKBD_IS_MDAT(data) && sc->sc_state == AS_MDAT) {
419 arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0);
420 arckbd_mousemoved(self, sc->sc_byteone, data);
423 /* Key down data */
424 else if (ARCKBD_IS_KDDA(data) && sc->sc_state == AS_IDLE) {
425 arckbd_send(self, ARCKBD_BACK, AS_KDDA, 0);
426 sc->sc_byteone = data;
427 } else if (ARCKBD_IS_KDDA(data) && sc->sc_state == AS_KDDA) {
428 arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0);
429 arckbd_keyupdown(self, sc->sc_byteone, data);
432 /* Key up data */
433 else if (ARCKBD_IS_KUDA(data) && sc->sc_state == AS_IDLE) {
434 arckbd_send(self, ARCKBD_BACK, AS_KUDA, 0);
435 sc->sc_byteone = data;
436 } else if (ARCKBD_IS_KUDA(data) && sc->sc_state == AS_KUDA) {
437 arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0);
438 arckbd_keyupdown(self, sc->sc_byteone, data);
441 /* Other cruft */
442 else if (ARCKBD_IS_KBID(data)) {
443 arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0);
444 if (sc->sc_kbid != data) {
445 printf("%s: layout %d\n",
446 device_xname(self), data & ~ARCKBD_KBID);
447 sc->sc_kbid = data;
449 } else if (ARCKBD_IS_PDAT(data))
450 /* unused -- ignore it */;
451 else {
452 /* Protocol error */
453 log(LOG_WARNING, "%s: protocol error: got 0x%02x in state %s\n",
454 device_xname(self), data, arckbd_statenames[sc->sc_state]);
455 arckbd_send(self, ARCKBD_HRST, AS_HRST, 0);
457 return IRQ_HANDLED;
460 static void
461 arckbd_mousemoved(device_t self, int byte1, int byte2)
463 #if NRND > 0 || NWSMOUSE > 0
464 struct arckbd_softc *sc = device_private(self);
465 #endif
467 #if NRND > 0
468 rnd_add_uint32(&sc->sc_rnd_source, byte1);
469 #endif
470 #if NWSMOUSE > 0
471 if (sc->sc_wsmousedev != NULL) {
472 int dx, dy;
474 /* deltas are 7-bit signed */
475 dx = byte1 < 0x40 ? byte1 : byte1 - 0x80;
476 dy = byte2 < 0x40 ? byte2 : byte2 - 0x80;
477 wsmouse_input(sc->sc_wsmousedev,
478 sc->sc_mouse_buttons,
479 dx, dy, 0, 0,
480 WSMOUSE_INPUT_DELTA);
482 #endif
485 static void
486 arckbd_keyupdown(device_t self, int byte1, int byte2)
488 struct arckbd_softc *sc = device_private(self);
489 u_int type;
490 int value;
492 #if NRND > 0
493 rnd_add_uint32(&sc->sc_rnd_source, byte1);
494 #endif
495 if ((byte1 & 0x0f) == 7) {
496 /* Mouse button event */
498 * This is all very silly, as the wsmouse driver then
499 * differentiates the button state to see if there's
500 * an event worth passing to the user.
502 * Oh well, at least NetBSD and Acorn number their
503 * mouse buttons the same way.
505 if (ARCKBD_IS_KDDA(byte1))
506 sc->sc_mouse_buttons |= (1 << (byte2 & 0x0f));
507 else
508 sc->sc_mouse_buttons &= ~(1 << (byte2 & 0x0f));
509 #if NWSMOUSE > 0
510 if (sc->sc_wsmousedev != NULL)
511 wsmouse_input(sc->sc_wsmousedev,
512 sc->sc_mouse_buttons,
513 0, 0, 0, 0,
514 WSMOUSE_INPUT_DELTA);
515 #endif
516 } else {
517 type = ARCKBD_IS_KDDA(byte1) ?
518 WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;
519 value = ((byte1 & 0x0f) << 4) | (byte2 & 0x0f);
520 if (sc->sc_flags & AKF_POLLING) {
521 sc->sc_poll_type = type;
522 sc->sc_poll_value = value;
524 #if NWSKBD > 0
525 else if (sc->sc_wskbddev != NULL)
526 wskbd_input(sc->sc_wskbddev, type, value);
527 #endif
532 * Keyboard access functions
535 static int
536 arckbd_enable(void *cookie, int on)
538 struct arckbd_softc *sc = cookie;
540 if (on) {
541 sc->sc_flags |= AKF_WANTKBD;
542 /* XXX send RQMP? */
543 } else
544 sc->sc_flags &= ~ AKF_WANTKBD;
545 return 0;
548 static int
549 arckbd_led_encode(int wsleds)
551 int arcleds;
553 arcleds = 0;
554 if (wsleds & WSKBD_LED_CAPS)
555 arcleds |= ARCKBD_LEDS_CAPSLOCK;
556 if (wsleds & WSKBD_LED_NUM)
557 arcleds |= ARCKBD_LEDS_NUMLOCK;
558 if (wsleds & WSKBD_LED_SCROLL)
559 arcleds |= ARCKBD_LEDS_SCROLLLOCK;
560 /* No "compose" LED */
561 return arcleds;
564 static int
565 arckbd_led_decode(int arcleds)
567 int wsleds;
569 wsleds = 0;
570 if (arcleds & ARCKBD_LEDS_CAPSLOCK)
571 wsleds |= WSKBD_LED_CAPS;
572 if (arcleds & ARCKBD_LEDS_NUMLOCK)
573 wsleds |= WSKBD_LED_NUM;
574 if (arcleds & ARCKBD_LEDS_SCROLLLOCK)
575 wsleds |= WSKBD_LED_SCROLL;
576 /* No "compose" LED */
577 return wsleds;
581 * Set the LEDs to the requested state.
583 * Be warned: This function gets called from interrupts.
585 static void
586 arckbd_set_leds(void *cookie, int new_state)
588 struct arckbd_softc *sc = cookie;
589 int s;
591 s = spltty();
592 sc->sc_leds = arckbd_led_encode(new_state);
593 if (arckbd_send(sc->sc_dev, ARCKBD_LEDS | sc->sc_leds, AS_IDLE, 0) == 0)
594 sc->sc_flags |= AKF_SENTLEDS;
595 splx(s);
598 /* ARGSUSED */
599 static int
600 arckbd_ioctl(void *cookie, u_long cmd, void *data, int flag, struct lwp *l)
602 struct arckbd_softc *sc = cookie;
604 switch (cmd) {
605 case WSKBDIO_GTYPE:
606 *(int *)data = WSKBD_TYPE_ARCHIMEDES;
607 return 0;
608 case WSKBDIO_SETLEDS:
609 arckbd_set_leds(sc, *(int *)data);
610 return 0;
611 case WSKBDIO_GETLEDS:
612 *(int *)data = arckbd_led_decode(sc->sc_leds);
613 return 0;
615 return EPASSTHROUGH;
619 * Mouse access functions
622 static int
623 arcmouse_enable(void *cookie)
625 struct arckbd_softc *sc = cookie;
627 sc->sc_flags |= AKF_WANTMOUSE;
628 /* XXX send RQMP */
629 return 0;
632 /* ARGSUSED */
633 static int
634 arcmouse_ioctl(void *cookie, u_long cmd, void *data, int flag, struct lwp *l)
636 /* struct arckbd_softc *sc = cookie; */
638 switch (cmd) {
639 case WSMOUSEIO_GTYPE:
640 *(int *)data = WSMOUSE_TYPE_ARCHIMEDES;
641 return 0;
643 return EPASSTHROUGH;
646 static void
647 arcmouse_disable(void *cookie)
649 struct arckbd_softc *sc = cookie;
651 sc->sc_flags &= ~AKF_WANTMOUSE;