2 * Copyright © 1999 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
24 #include <kdrive-config.h>
33 #include <sys/ioctl.h>
34 #include <X11/keysym.h>
35 #include <linux/apm_bios.h>
44 LinuxVTRequest (int sig
)
46 kdSwitchPending
= TRUE
;
49 /* Check before chowning -- this avoids touching the file system */
51 LinuxCheckChown (char *file
)
57 if (stat (file
, &st
) < 0)
61 if (st
.st_uid
!= u
|| st
.st_gid
!= g
)
73 /* check if we're run with euid==0 */
76 FatalError("LinuxInit: Server must be suid root\n");
79 if (kdVirtualTerminal
>= 0)
80 vtno
= kdVirtualTerminal
;
83 if ((fd
= open("/dev/tty0",O_WRONLY
,0)) < 0)
86 "LinuxInit: Cannot open /dev/tty0 (%s)\n",
89 if ((ioctl(fd
, VT_OPENQRY
, &vtno
) < 0) ||
92 FatalError("xf86OpenConsole: Cannot find a free VT\n");
97 sprintf(vtname
,"/dev/tty%d",vtno
); /* /dev/tty1-64 */
99 if ((LinuxConsoleFd
= open(vtname
, O_RDWR
|O_NDELAY
, 0)) < 0)
101 FatalError("LinuxInit: Cannot open %s (%s)\n",
102 vtname
, strerror(errno
));
105 /* change ownership of the vt */
106 LinuxCheckChown (vtname
);
109 * the current VT device we're running on is not "console", we want
110 * to grab all consoles too
112 * Why is this needed?
114 LinuxCheckChown ("/dev/tty0");
116 * Linux doesn't switch to an active vt after the last close of a vt,
117 * so we do this ourselves by remembering which is active now.
119 memset (&vts
, '\0', sizeof (vts
)); /* valgrind */
120 if (ioctl(LinuxConsoleFd
, VT_GETSTATE
, &vts
) == 0)
122 activeVT
= vts
.v_active
;
129 LinuxFindPci (CARD16 vendor
, CARD16 device
, CARD32 count
, KdCardAttr
*attr
)
132 char line
[2048], *l
, *end
;
133 CARD32 bus
, id
, addr
;
139 attr
->vendorID
= vendor
;
140 attr
->deviceID
= device
;
141 ven_dev
= (((CARD32
) vendor
) << 16) | ((CARD32
) device
);
142 f
= fopen ("/proc/bus/pci/devices", "r");
146 while (fgets (line
, sizeof (line
)-1, f
))
148 line
[sizeof(line
)-1] = '\0';
150 bus
= strtoul (l
, &end
, 16);
154 id
= strtoul (l
, &end
, 16);
162 (void) strtoul (l
, &end
, 16); /* IRQ */
167 for (i
= 0; i
< 6; i
++)
169 addr
= strtoul (l
, &end
, 16);
173 attr
->io
= addr
& ~0xf;
176 if (n
== KD_MAX_CARD_ADDRESS
)
178 attr
->address
[n
++] = addr
& ~0xf;
184 if (attr
->address
[n
-1] != 0)
189 attr
->domain
= 0; /* XXX */
190 attr
->bus
= (bus
>> 8) & 0xff;
191 attr
->slot
= (bus
>> 3) & 0x1f;
192 attr
->func
= bus
& 0x07;
201 LinuxGetPciCfg(KdCardAttr
*attr
)
208 snprintf(filename
, 255, "/proc/bus/pci/%02x/%02x.%x",
209 attr
->bus
>> 8, (attr
->bus
& 0xff) >> 3, attr
->bus
& 7);
210 /* fprintf(stderr,"Find card on path %s\n",filename); */
212 if (!(f
=fopen(filename
,"r")))
215 if (!(cfg
=xalloc(256)))
221 if (256 != (r
=fread(cfg
, 1, 256, f
)))
223 fprintf(stderr
,"LinuxGetPciCfg: read %d, expected 256\n",r
);
228 /* fprintf(stderr,"LinuxGetPciCfg: success, returning %p\n",cfg); */
233 LinuxSetSwitchMode (int mode
)
235 struct sigaction act
;
238 if (ioctl(LinuxConsoleFd
, VT_GETMODE
, &VT
) < 0)
240 FatalError ("LinuxInit: VT_GETMODE failed\n");
243 if (mode
== VT_PROCESS
)
245 act
.sa_handler
= LinuxVTRequest
;
246 sigemptyset (&act
.sa_mask
);
248 sigaction (SIGUSR1
, &act
, 0);
256 act
.sa_handler
= SIG_IGN
;
257 sigemptyset (&act
.sa_mask
);
259 sigaction (SIGUSR1
, &act
, 0);
265 if (ioctl(LinuxConsoleFd
, VT_SETMODE
, &VT
) < 0)
267 FatalError("LinuxInit: VT_SETMODE failed\n");
272 LinuxApmBlock (pointer blockData
, OSTimePtr pTimeout
, pointer pReadmask
)
276 static Bool LinuxApmRunning
;
279 LinuxApmWakeup (pointer blockData
, int result
, pointer pReadmask
)
281 fd_set
*readmask
= (fd_set
*) pReadmask
;
283 if (result
> 0 && LinuxApmFd
>= 0 && FD_ISSET (LinuxApmFd
, readmask
))
286 Bool running
= LinuxApmRunning
;
287 int cmd
= APM_IOC_SUSPEND
;
289 while (read (LinuxApmFd
, &event
, sizeof (event
)) == sizeof (event
))
292 case APM_SYS_STANDBY
:
293 case APM_USER_STANDBY
:
295 cmd
= APM_IOC_STANDBY
;
297 case APM_SYS_SUSPEND
:
298 case APM_USER_SUSPEND
:
299 case APM_CRITICAL_SUSPEND
:
301 cmd
= APM_IOC_SUSPEND
;
303 case APM_NORMAL_RESUME
:
304 case APM_CRITICAL_RESUME
:
305 case APM_STANDBY_RESUME
:
310 if (running
&& !LinuxApmRunning
)
313 LinuxApmRunning
= TRUE
;
315 else if (!running
&& LinuxApmRunning
)
318 LinuxApmRunning
= FALSE
;
319 ioctl (LinuxApmFd
, cmd
, 0);
325 #define NOBLOCK FNONBLOCK
327 #define NOBLOCK FNDELAY
337 kdSwitchPending
= FALSE
;
338 ioctl (LinuxConsoleFd
, VT_RELDISP
, VT_ACKACQ
);
341 * Open the APM driver
343 LinuxApmFd
= open ("/dev/apm_bios", 2);
344 if (LinuxApmFd
< 0 && errno
== ENOENT
)
345 LinuxApmFd
= open ("/dev/misc/apm_bios", 2);
348 LinuxApmRunning
= TRUE
;
349 fcntl (LinuxApmFd
, F_SETFL
, fcntl (LinuxApmFd
, F_GETFL
) | NOBLOCK
);
350 RegisterBlockAndWakeupHandlers (LinuxApmBlock
, LinuxApmWakeup
, 0);
351 AddEnabledDevice (LinuxApmFd
);
357 LinuxSetSwitchMode (VT_AUTO
);
358 if (ioctl(LinuxConsoleFd
, VT_ACTIVATE
, vtno
) != 0)
360 FatalError("LinuxInit: VT_ACTIVATE failed\n");
362 if (ioctl(LinuxConsoleFd
, VT_WAITACTIVE
, vtno
) != 0)
364 FatalError("LinuxInit: VT_WAITACTIVE failed\n");
366 LinuxSetSwitchMode (VT_PROCESS
);
367 if (ioctl(LinuxConsoleFd
, KDSETMODE
, KD_GRAPHICS
) < 0)
369 FatalError("LinuxInit: KDSETMODE KD_GRAPHICS failed\n");
377 ioctl(LinuxConsoleFd
, KDSETMODE
, KD_TEXT
); /* Back to text mode ... */
380 kdSwitchPending
= FALSE
;
381 ioctl (LinuxConsoleFd
, VT_RELDISP
, 1);
386 RemoveBlockAndWakeupHandlers (LinuxApmBlock
, LinuxApmWakeup
, 0);
387 RemoveEnabledDevice (LinuxApmFd
);
400 if (LinuxConsoleFd
< 0)
403 if (ioctl(LinuxConsoleFd
, VT_GETMODE
, &VT
) != -1)
406 ioctl(LinuxConsoleFd
, VT_SETMODE
, &VT
); /* set dflt vt handling */
408 memset (&vts
, '\0', sizeof (vts
)); /* valgrind */
409 ioctl (LinuxConsoleFd
, VT_GETSTATE
, &vts
);
410 if (vtno
== vts
.v_active
)
413 * Find a legal VT to switch to, either the one we started from
414 * or the lowest active one that isn't ours
417 activeVT
== vts
.v_active
||
418 !(vts
.v_state
& (1 << activeVT
)))
420 for (activeVT
= 1; activeVT
< 16; activeVT
++)
421 if (activeVT
!= vtno
&& (vts
.v_state
& (1 << activeVT
)))
427 * Perform a switch back to the active VT when we were started
431 ioctl (LinuxConsoleFd
, VT_ACTIVATE
, activeVT
);
432 ioctl (LinuxConsoleFd
, VT_WAITACTIVE
, activeVT
);
436 close(LinuxConsoleFd
); /* make the vt-manager happy */
438 fd
= open ("/dev/tty0", O_RDWR
|O_NDELAY
, 0);
441 memset (&vts
, '\0', sizeof (vts
)); /* valgrind */
442 ioctl (fd
, VT_GETSTATE
, &vts
);
443 if (ioctl (fd
, VT_DISALLOCATE
, vtno
) < 0)
444 fprintf (stderr
, "Can't deallocate console %d errno %d\n", vtno
, errno
);
451 KdOsAddInputDrivers ()
453 KdAddPointerDriver(&LinuxMouseDriver
);
454 KdAddPointerDriver(&MsMouseDriver
);
455 KdAddPointerDriver(&Ps2MouseDriver
);
457 KdAddPointerDriver(&TsDriver
);
459 KdAddPointerDriver(&LinuxEvdevMouseDriver
);
460 KdAddKeyboardDriver(&LinuxKeyboardDriver
);
461 KdAddKeyboardDriver(&LinuxEvdevKeyboardDriver
);
465 LinuxBell(int volume
, int pitch
, int duration
)
468 ioctl(LinuxConsoleFd
, KDMKTONE
, ((1193190 / pitch
) & 0xffff) |
469 (((unsigned long)duration
* volume
/ 50) << 16));
472 KdOsFuncs LinuxFuncs
= {
474 .Enable
= LinuxEnable
,
475 .Disable
= LinuxDisable
,
483 KdOsInit (&LinuxFuncs
);