flagday-log WIP, jenkins testing only
Squashed commit of the following:
commit 7414eb808dfbce800e2dfaa3ca7f5474ba2d3684
Author: David van Moolenbroek <david@minix3.org>
Date: Sat Sep 21 17:35:15 2013 +0200
Take LOG out of the boot image
Change-Id: Id2629776b53aae46629b04a42c15cbbacac9b949
commit aa33a6af33169916d081f27e22fb7ca458e92022
Author: David van Moolenbroek <david@minix3.org>
Date: Sat Sep 21 15:03:20 2013 +0200
Kernel: make SIGKMESS target process list dynamic
The set of processes to which a SIGKMESS signal is sent whenever new
diagnostics messages are added to the kernel's message buffer, is now
no longer hardcoded. Instead, processes can (un)register themselves
to receive such notifications, by means of sys_diagctl().
Change-Id: I9d6ac006a5d9bbfad2757587a068fc1ec3cc083e
commit 4991d187e7efcf6348fa761c45414938c99bf048
Author: David van Moolenbroek <david@minix3.org>
Date: Sat Sep 21 00:58:46 2013 +0200
Rename SYSCTL kernel call to DIAGCTL
Change-Id: I1b17373f01808d887dcbeab493838946fbef4ef6
commit 4ac2419358f96fbafc6fdc2df14c716c232d830f
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Sep 18 20:13:59 2013 +0200
Prevent Jenkins from breaking on old df(1)
Change-Id: Ie8e1758bd9de4d5c95c597302f80d568058fbb68
commit 9b17c22cf13b68bf063024be1de56813ea29940b
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Sep 18 14:09:47 2013 +0200
Add testvnd.sh test script
As part of this, change the "run" script to allow certain scripts to
be run as root only.
Change-Id: I846e41037f9d4f6c7fc0b5ea8250303a7bd72f5d
commit 8cde906ba03b1e9aaf2ebb1fdd990452e3d3c016
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Sep 18 14:06:46 2013 +0200
Import NetBSD vndconfig(8)
The tool has been changed heavily to match our VND driver model.
NetBSD is in the process of renaming it from vnconfig(8) to
vndconfig(8). To keep things in sync, we have to play along.
Change-Id: Ie86df184f03ab00573ea76b43c9caa0412e8321d
commit 0088920e85160ebe6f04eb6913a629a2f5c9a582
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Sep 18 14:02:17 2013 +0200
Add VND driver, providing loopback devices
Change-Id: I40fa695e28c67477a75383e6f1550e451afcab41
commit 0998c7cbcc8eb934f28830f3f5ba2e312c740ae9
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Sep 18 13:55:15 2013 +0200
VFS: add dupfrom(2) call
This call copies a file descriptor from a remote process into the
calling process. The call is for the VND driver only, and in the
future, ACLs will prevent any other process from using this call.
Change-Id: Ib16fdd1f1a12cb38a70d7e441dad91bc86898f6d
commit ca15ee79df5cc00b93464f83e823a02374dcf609
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Sep 18 11:46:08 2013 +0200
tests: do not skip installed shell tests
When installed, the test scripts lose their ".sh" suffix, causing them
to be skipped by the "run" script. With this patch, the tests are no
longer specified with ".sh" suffix in the run script, and the suffix
is added automatically as necessary.
Change-Id: I0b72312e79992b9818559c6546a0e52cd95184c2
commit a1b6eb025e61d23c39c7dfa07281bf8a52256648
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Sep 18 13:41:56 2013 +0200
blocktest: prepare to be run as part of tests
- fail SEF initialization if any of the subtests failed, so that the
party invoking the "service up" can tell whether the test succeeded;
- add "nocontig" option, because VM isn't particularly good at
allocating contiguous memory;
- add "silent" option, because it floods the console otherwise;
- allow the device size to be smaller than the maximum transfer size;
- install files to installed test directory.
Change-Id: I45c818f817c11d90c5f94ae26a2fc49e36e6761e
commit 27e85d168b5b0de4bd5dad71110a28ab7de1c506
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Sep 18 13:38:36 2013 +0200
Enable devname(3)
There is no support for a device name database yet, so this call is
expected to be fairly slow.
Change-Id: I73aa5f267e2b6921b7d3bbdcc4beac463931132c
commit 9db9e3e97cd10f114f3b25e2f9f192023fee409d
Author: David van Moolenbroek <david@minix3.org>
Date: Sun Sep 15 13:09:00 2013 +0200
libbdev: be less noisy about clean driver restarts
Change-Id: Ie02a459c9b544d361ab00bac431ef99de53b0c5f
commit 967b189e814cdd02d253d7c877bc4dbd7552f8b8
Author: David van Moolenbroek <david@minix3.org>
Date: Sat Sep 14 14:43:53 2013 +0200
Straighten ioctl.h
- include all ioctl subheaders, properly listing all letters;
- change FBD's ioctl calls to use 'B' instead of 'F', in
preparation of the VND driver.
Change-Id: Ia718979568cc057f47cf505a89238d5b3b6695d4
commit 0ec080b7a65598d66e8ff01d559993c27e91c026
Author: David van Moolenbroek <david@minix3.org>
Date: Sun Sep 15 18:55:42 2013 +0200
VM: readd support for forgetting cached FS blocks
Not all services involved in block I/O go through VM to access the
blocks they need. As a result, the blocks in VM may become stale,
possibly causing corruption when the stale copy is restored by a
service that does go through VM later on. This patch restores support
for forgetting cached blocks that belong to a particular device, and
makes the relevant file systems use this functionality 1) when
requested by VFS through REQ_FLUSH, and 2) upon unmount.
Change-Id: I0758c5ed8fe4b5ba81d432595d2113175776aff8
commit b13082423d41cbb21f38348c96e5ada4c550b4bd
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Sep 11 14:50:18 2013 +0200
filter: use libblockdriver
Change-Id: Ifbca2482e996ddca58036d45f557165e636fb3fa
commit 66d9724e08f8ec256f1fcfba65cb16eec9c62bfb
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Sep 10 20:25:01 2013 +0200
Rewrite character driver protocol
As a side effect, remove the clone style, as the normal device style
supports device cloning now.
Change-Id: Ie82d1ef0385514a04a8faa139129a617895780b5
commit 0026fc3de77b5f4c70d72eb0320b0b92d9fe0066
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Sep 10 16:06:37 2013 +0200
Remove support for reopening character devices
Previously, VFS would reopen a character device after a driver crash
if the associated file descriptor was opened with the O_REOPEN flag.
This patch removes support for this feature. The code was complex,
full of uncovered corner cases, and hard to test. Moreover, it did not
actually hide the crash from user applications: they would get an
error code to indicate that something went wrong, and have to decide
based on the nature of the underlying device how to continue.
- remove support for O_REOPEN, and make playwave(1) reopen its device;
- remove support for the DEV_REOPEN protocol message;
- remove all code in VFS related to reopening character devices;
- no longer change VFS filp reference count and FD bitmap upon filp
invalidation; instead, make get_filp* fail all calls on invalidated
FDs except when obtained with the locktype VNODE_OPCL which is used
by close_fd only;
- remove the VFS fproc file descriptor bitmap entirely, returning to
the situation that a FD is in use if its slot points to a filp; use
FILP_CLOSED as single means of marking a filp as invalidated.
Change-Id: I34f6bc69a036b3a8fc667c1f80435ff3af56558f
commit 6eaaa958390eb80b81dafef2068378a5ce2e2946
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Sep 10 12:19:08 2013 +0200
VFS: rework device code
- block the calling thread on character device close;
- fully separate block and character open/close routines;
- reuse generic open/close code for the cloning case;
- zero all messages to drivers before filling them;
- use appropriate types for major/minor device numbers.
Change-Id: Ia90e6fe5688f212f835c5ee1bfca831cb249cf51
commit 4ee8b6fab457a894c8e9c30310bff1ccc9f7d68b
Author: David van Moolenbroek <david@minix3.org>
Date: Mon Sep 9 00:04:12 2013 +0200
Make PFS backcalls regular VFS calls
- prefix them with VFS_ as they are going to VFS;
- give these calls normal call numbers;
- give them their own set of message field aliases;
- also make do_mapdriver a regular call.
Change-Id: I2140439f288b06d699a1f65438bd8306509b259e
commit 367106e9e89dbae83b3dc3f946518ed6c93e3c4d
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Sep 11 12:48:10 2013 +0200
TTY: use libchardriver; clean up
- writing to a PTY master side blocks if there is not already a
blocked reader on the slave side, and select now reflects this;
- internally, TTY now uses a test based on "caller != NONE" rather
than "grant != GRANT_INVALID" to identify whether a call is
currently ongoing;
- "offset" fields have been removed as they equal the corresponding
"cum" fields;
- improved variable typing and function naming here and there;
- various other small fixes.
Change-Id: I6b51452888942e864b4e034e8c8490576184a23e
commit e90437f66a75169e30f3aab114de37659a238492
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Sep 11 01:13:59 2013 +0200
VFS: select(2) fixes
- check each file descriptor's open access mode (filp_mode);
- treat an error returned by a character driver as a select error;
- check all filps in each set before finishing select;
- do not copy back file descriptor sets if an error occurred;
- remove the hardcoded list of supported character major devices,
since all drivers should now be capable of responding properly;
- add tests to test40 and fix its error count aggregation.
Change-Id: I57ef58d3afb82640fc50b59c859ee4b25f02db17
commit db849cabad84c98f5d37c79dab4f5ed2e4471d78
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Sep 11 01:07:28 2013 +0200
Retire EBADIOCTL in favor of ENOTTY
Change-Id: I6bd0e301d21ab7f2336e350e7e6e15d238c2c93d
commit 8ab3ef8007f241dff9fbdabc47b4d4da7faf8d8e
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Sep 4 15:42:36 2013 +0000
libnetsock: use libchardriver
Change-Id: Ia5b780cad0b0c636db9bd866c7223da0d38ef6ea
commit 1c1d697cb2bdcb8dd456b0dee757ec09032e689c
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Sep 11 00:50:36 2013 +0200
LWIP: move chardev message parsing into libnetsock
Change-Id: Ie23fd003c9fa35811548f388c8e9b55e8d9de8d7
commit bbbeccd4fa5b2f0ab9c670bb6165eddfe7c95988
Author: David van Moolenbroek <david@minix3.org>
Date: Mon Sep 9 14:53:28 2013 +0000
INET: use libchardriver
Change-Id: Icf8a1a5769ce0aede1cc28da99b9daf7d328182c
commit 1db6dc9bc7352c87dbbdfc2a6b235572fc456b86
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Sep 3 02:00:20 2013 +0200
PFS: use libchardriver; clean up
- simplify and repair UDS request handling state machine;
- simplify interface used between internal modules;
- implement missing support for nonblocking I/O;
- fix select implementation;
- clean up global variables.
Change-Id: Ia82c5c6f05cc3f0a498efc9a26de14b1cde6eace
commit 1dd909f41c50f34f8d892fb2624a635bca39e983
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Sep 3 01:59:20 2013 +0200
libaudiodriver: use libchardriver
Change-Id: I299d58d110ad14b69076276ba46c4325875c34ca
commit c0047f6a442a12c13f439969eca425c1bc4c2997
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Sep 3 01:57:41 2013 +0200
printer: use libchardriver
Change-Id: Ifa3cabeada74c32df2613b8279c00f86e831c775
commit 35539543724128287f42425ab053deffb97ab78e
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Sep 3 01:49:38 2013 +0200
libchardriver: full API rewrite
The new API now covers the entire character driver protocol, while
hiding all the message details. It should therefore be used by all
new character drivers. All existing drivers that already made use of
libchardriver have been changed to use the new API.
As one of the most important API changes, support for scatter and
gather transfers has been removed, as several key drivers already
did not support this, and it could be supported at the safecopy
level instead (for a future readv/writev).
Additional changes include:
- respond to block device open requests to avoid hanging VFS threads;
- add support for sef_cancel.
Change-Id: I1bab6c1cb66916c71b87aeb1db54a9bdf171fe6b
commit 521df439aaff6012c91b39281c2e0101c088c6c3
Author: David van Moolenbroek <david@minix3.org>
Date: Thu Aug 1 18:20:33 2013 +0200
blocktest: add support for no alignment
Some block drivers do not impose any alignment requirements, and this
patch allows such block drivers to pass the test set. As a side effect,
minimal support for min_write is added, but this part of blocktest is
in need of further improvement.
commit faa0389acea11c3aa4dd1ba1e5169385675442a5
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Apr 18 00:04:28 2012 +0200
libutil: let opendisk(3) try /dev
If a device node is given without path, and opening the node fails
initially, prepend "/dev/" to the node name and try opening again.
This is more in line with NetBSD behavior.
commit f34bb193985eed63221c90c3ca48766c160c4fb4
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Sep 10 23:57:32 2013 +0200
Block drivers: make IOCTL request unsigned long
The block driver protocol and libblockdriver's bdr_ioctl hook are
changed, as well as the users of this hook. Other parts of the system
are expected to change accordingly eventually, since the ioctl(2)
prototype has been aligned with NetBSD's.
Change-Id: Ide46245b22cfa89ed267a38088fb0ab7696eba92
commit 2c70e7b0ee997654eb9ac48034325b29c3ab80ab
Author: David van Moolenbroek <david@minix3.org>
Date: Sat Jul 27 00:49:49 2013 +0200
Block protocol: add user endpoint to IOCTL request
I/O control requests now come with the endpoint of the user process
that initiated the ioctl(2) call. It is stored in a new BDEV_USER
field, which is an alias for BDEV_FLAGS. The contents of this field
are to be used only in highly specific situations. It should be
preserved (not replaced!) by services that forward IOCTL requests,
and may be set to NONE for service-initiated IOCTL requests.
Change-Id: I68a01b9ce43eca00e61b985a9cf87f55ba683de4
commit 622e08ee49e14b54e064b85e912e83466f1cfe6f
Author: David van Moolenbroek <david@minix3.org>
Date: Sat Jul 27 00:49:49 2013 +0200
Block protocol: use own [RW]_BIT definitions
The original R_BIT and W_BIT definitions have nothing to do with the
way these bits are used. Their distinct usage is more apparent when
they have different names.
Change-Id: Ia984457f900078b2e3502ceed565fead4e5bb965
commit 49ddd9530a0909f9eadc324616a16c11b7ff5e56
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Sep 10 23:35:15 2013 +0200
libblockdriver: expose BLOCKDRIVER_MAX_DEVICES
This constant determines the range of valid device_id_t values that
a block driver can return from the bdr_device hook: a value between
0 and (BLOCKDRIVER_MAX_DEVICES - 1) inclusive.
Change-Id: I80fac469e88ac13d4b869007e6f2c2f7569da433
commit 07482d855ca11c45235673309beb1e26a1f389a0
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Sep 11 13:33:00 2013 +0200
libblockdriver: various updates
- internal structure rearrangement;
- respond to char device open requests to avoid hanging VFS threads;
- make drivers use designated initializers;
- use devminor_t for all minor device numbers;
- change bdr_other hook to take ipc_status and return nothing;
- fix default geometry computation;
- add support for sef_cancel.
Change-Id: Ia063a136a3ddb2b78de36180feda870605753d70
commit f1a1ebb711626107014408a1b6561f3a67c0b557
Author: David van Moolenbroek <david@minix3.org>
Date: Sun Sep 1 14:34:17 2013 +0200
Block drivers: reply ENOTTY to unknown IOCTLs
Change-Id: Ie2e82d2491d546f4dd73b009100646e249a147b5
commit b3f90bcbd9bf3e205624eccdcbfda3b349469bc5
Author: David van Moolenbroek <david@minix3.org>
Date: Sun Jul 28 14:03:07 2013 +0200
Move SUB_PER_DRIVE definition into minix/drvlib.h
commit 478389a9ccc93974ad4158158e34b2d6d44441de
Author: David van Moolenbroek <david@minix3.org>
Date: Mon Sep 2 17:34:44 2013 +0200
VFS: update filp_pos on chardev I/O (workaround)
Previously, reading from or writing to a character device would not
update the file position on the corresponding filp object. Performing
this update correctly is not trivial: during and after the I/O
operation, the filp object must not be locked. Ideally, read/write
requests on a filp that is already involved in a read/write operation,
should be queued. For now, we optimistically update the file position
at the start of the I/O; this works under the assumptions listed in
the corresponding comment.
Change-Id: I172a61781850423709924390ae3df1f2d1f94707
commit 267c676b8867652666e74cfa4a6e21b7205e163c
Author: David van Moolenbroek <david@minix3.org>
Date: Mon Sep 2 13:45:02 2013 +0200
I2C: change BUSC_I2C_xxx to use own protocol
Previously it would use bits of the character driver protocol, which
will change heavily. In the new situation, the BUSC_I2C_xxx requests
use a protocol more in line with the PCI protocol, with the reply code
in m_type.
Change-Id: I51597b3f191078c8178ce17372de123031f7a4c4
commit ce5af0be47886f2b2aaf399cc93d5d1d839d180a
Author: David van Moolenbroek <david@minix3.org>
Date: Sat Aug 31 16:13:37 2013 +0200
tests: add test77 for opening/closing PTYs
Change-Id: I30e3418f75137aa08037fa6581ff3d4cce32a114
commit 302841555f16077f611539e0df24f9f11f32803a
Author: David van Moolenbroek <david@minix3.org>
Date: Sat Aug 31 16:08:25 2013 +0200
TTY: fix for PTY open/close logic
Opening and closing the master side of a pseudo terminal without
opening the slave side would result in the pseudo terminal becoming
permanently unavailable. In addition, reopening the slave side
would be possible but not allow for I/O. Finally, attempting to
open an in-use master would wipe its I/O state. These issues have
been resolved.
Change-Id: I9235e3d9aba321803f9280b86b6b5e3646ad5ef3
commit 3cd3c37232291e16cddb8fcfaf3f5da518874bb1
Author: David van Moolenbroek <david@minix3.org>
Date: Fri Aug 30 18:48:56 2013 +0200
tests: remove select subdirectory
This test set has been obsoleted by test40.
Change-Id: I55439152824906778ad07d409dfb327ac10bea70
commit d165339702810b72812d6e3c8730afe6f4da0579
Author: David van Moolenbroek <david@minix3.org>
Date: Fri Aug 30 18:43:23 2013 +0200
tests: add test76 for interrupting VFS operations
Change-Id: Ic436cac61de8c42e0c7ee2d442c647528654cde9
commit befe9861f6e4bad449e65f32692376fbd2eafebc
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Aug 28 13:08:16 2013 +0200
VFS: fix interruption of blocking pipe operations
POSIX states that when interrupted, partially successful pipe
operations should return the partial result rather than EINTR. VFS
previously wouldn't look at the partial result, and not clear it
either, which would result in a panic upon the next pipe operation.
Change-Id: Ia1eb72b4b77394051444e63a1390d49bb315eb04
commit 40bde438305a1fe9ae6285ef17703f3b2c119c3e
Author: David van Moolenbroek <david@minix3.org>
Date: Fri Aug 30 00:57:16 2013 +0200
libmthread: do not dump stack for free threads
Change-Id: Ic438a252f5bddaf1513f554c71173e6fffb0c674
commit 6687b172462e623c6fc76e785f20d15ccdb8bea0
Author: David van Moolenbroek <david@minix3.org>
Date: Fri Aug 30 14:00:50 2013 +0200
VFS: worker thread model overhaul
The main purpose of this patch is to fix handling of unpause calls
from PM while another call is ongoing. The solution to this problem
sparked a full revision of the threading model, consisting of a large
number of related changes:
- all active worker threads are now always associated with a process,
and every process has at most one active thread working for it;
- the process lock is always held by a process's worker thread;
- a process can now have both normal work and postponed PM work
associated to it;
- timer expiry and non-postponed PM work is done from the main thread;
- filp garbage collection is done from a thread associated with VFS;
- reboot calls from PM are now done from a thread associated with PM;
- the DS events handler is protected from starting multiple threads;
- support for a system worker thread has been removed;
- the deadlock recovery thread has been replaced by a parameter to the
worker_start() function; the number of worker threads has
consequently been increased by one;
- saving and restoring of global but per-thread variables is now
centralized in worker_suspend() and worker_resume(); err_code is now
saved and restored in all cases;
- the concept of jobs has been removed, and job_m_in now points to a
message stored in the worker thread structure instead;
- the PM lock has been removed;
- the separate exec lock has been replaced by a lock on the VM
process, which was already being locked for exec calls anyway;
- PM_UNPAUSE is now processed as a postponed PM request, from a thread
associated with the target process;
- the FP_DROP_WORK flag has been removed, since it is no longer more
than just an optimization and only applied to processes operating on
a pipe when getting killed;
- assignment to "fp" now takes place only when obtaining new work in
the main thread or a worker thread, when resuming execution of a
thread, and in the special case of exiting processes during reboot;
- there are no longer special cases where the yield() call is used to
force a thread to run.
Change-Id: I7a97b9b95c2450454a9b5318dfa0e6150d4e6858
commit 18adf3b3481cb93d48990ca6c27779d3354ed92e
Author: David van Moolenbroek <david@minix3.org>
Date: Wed Aug 28 15:58:30 2013 +0200
Retire ptrace(T_DUMPCORE), dumpcore(1), gcore(1)
The T_DUMPCORE implementation was not only broken - it would currently
produce a coredump of the tracer process rather than the traced
process - but also deeply flawed, and fixing it would require serious
alteration of PM's internal state machine. It should be possible to
implement the same functionality in userland, and that is now the
suggested way forward. For now, also remove the (identical) utilities
using T_DUMPCORE: dumpcore(1) and gcore(1).
Change-Id: I1d51be19c739362b8a5833de949b76382a1edbcc
commit c89c9bba1242ab64f00e33a7c103491d16a5dcc4
Author: David van Moolenbroek <david@minix3.org>
Date: Fri Aug 30 13:42:51 2013 +0200
VFS: process char driver replies from main thread
Previously, processing of some replies coming from character drivers
could block on locks, and therefore, such processing was done from
threads that were associated to the character driver process. The
hidden consequence of this was that if all threads were in use, VFS
could drop replies coming from the driver. This patch returns VFS to
a situation where the replies from character drivers are processed
instantly from the main thread, by removing the situations that may
cause VFS to block while handling those replies.
- change the locking model for select, so that it will never block
on any processing that happens after the select call has been set
up, in particular processing of character driver select replies;
- clearly mark all select routines that may never block;
- protect against race conditions in do_select as result of the
locking that still does happen there (as is required for pipes);
- also handle select timers from the main thread;
- move processing of character driver replies into device.c.
Change-Id: I4dc8e69f265cbd178de0fbf321d35f58f067cc57
commit 4bafbd90372f7e6e5e37a9961e2da732597a5462
Author: David van Moolenbroek <david@minix3.org>
Date: Sun Aug 25 00:26:38 2013 +0200
VFS: properly cancel select queries on unpause
Change-Id: I16e71db3f5c1bcc7ba6045bc9f02b13d71dc31eb
commit 6fbc144cbefcccbf2486d5d4077a90f9a73ba0d7
Author: David van Moolenbroek <david@minix3.org>
Date: Fri Aug 30 13:33:56 2013 +0200
VFS: remove support for sync char driver protocol
Change-Id: I57cc870a053b813b3a3fc45da46606ea84fe4cb1
commit 70d5e810f5b3b1d4be1069ef2b04c6ac3704c6ee
Author: David van Moolenbroek <david@minix3.org>
Date: Fri Aug 30 13:00:44 2013 +0200
VFS: remove FP_BLOCKED_ON_DOPEN
These days, DEV_OPEN calls to character drivers block the calling
thread until completion or failure, and thus never return SUSPEND to
the caller. The same already applied to BDEV_OPEN calls to block
drivers. It has thus become impossible for a process to enter a state
of being blocked on a device open call.
There is currently no support for restarting device open calls to
restarted character drivers. This support was present in the _DOPEN
logic, but was already no longer triggering. In the future, this case
should be handled by the thread performing the open request.
Change-Id: I6cc1e7b4c9ed116c6ce160b315e6e060124dce00
commit c3ddc6bbb23987af924ab4ae09bc2bbc12b29ca7
Author: David van Moolenbroek <david@minix3.org>
Date: Fri Aug 30 12:18:27 2013 +0200
PFS: remember request information for IOCTLs
Not doing so caused PFS to commit protocol violations by relying on
stale information when sending replies. This stale information always
happened to be correct, which is why the problem went unnoticed.
Change-Id: Ia42ca670718d6e731193cd2c34a3ff455f8a94d3
commit 61080f73325be2793e5175c17c9007ee0707b4ee
Author: David van Moolenbroek <david@minix3.org>
Date: Fri Aug 30 11:14:03 2013 +0200
Retire the synchronous character driver protocol
- change all sync char drivers into async drivers;
- retire support for the sync protocol in libchardev;
- remove async dev style, as this is now the default;
- remove dev_status from VFS;
- clean up now-unused protocol messages.
Change-Id: I6aacff712292f6b29f2ccd51bc1e7d7003723e87
commit 55e01bfda35e370a28841eed7017e091f7f55ba0
Author: David van Moolenbroek <david@minix3.org>
Date: Fri Aug 30 10:48:34 2013 +0200
Sync char protocol: add nonblocking transfer flag
The async char protocol already has this, so this patch closes the
gap between the two protocols a bit. Support for this flag has been
added to all sync char drivers that support CANCEL at all.
The LOG driver was already using the asynchronous protocol, but it
did not support the nonblocking transfer flag. This has been fixed
as well.
Change-Id: Ia55432c9f102765b59ad3feb45a8bd47a782c93f
commit fd34804e63e1ca6713c781f7437b4c60342d93e6
Author: David van Moolenbroek <david@minix3.org>
Date: Sat Aug 24 12:29:39 2013 +0200
VFS: set w_drv_sendrec only when needed
As with w_task, this ensures that the field remains cleared if it is
not used. Without this, worker_stop could mistakenly identify a thread
as talking to a device driver rather than a (crashed) file server.
Change-Id: I7d3ebed3efc3cd4f5c891f61c67a6463109b6376
commit ccbaf6bd8252ac5a2edeee4dd66fd1d43445a24e
Author: Thomas Veerman <thomas@minix3.org>
Date: Sat Aug 24 12:23:41 2013 +0200
VFS: set w_task only when needed
It was always set, but not always cleared, when talking to asynchronous
drivers. This could cause erratic behavior upon a driver crash.
Normally, a worker thread's w_task field is set when it's about to
communicate with a driver or FS. Then upon receiving a reply we can
do sanity checks (that the thread we want to wake up was actually
waiting for a reply). Also, when a driver/FS crashes, we can identify
which worker threads were talking to the crashed endpoint and handle
the error gracefully.
Asynchronous drivers are a bit special, though. In most cases, the
sender of the request is not interested in the reply (the sender was
suspended and only wants to know whether the request was successfully
caried out or not). However, the open request is special, as the reply
carries information needed by the sender. This is the only request
where a worker thread actually yields and waits for the result. This is
also the only case where we're interested in setting w_task for
asynchronous drivers.
Change-Id: Ia1ce2747937df376122b5e13b6a069de27fcc379
commit 80e6a4c121a64fc77cc5dfa0e33dfbd69ec2ea1a
Author: David van Moolenbroek <david@minix3.org>
Date: Mon Aug 19 20:34:15 2013 +0200
Import NetBSD df(1)
Change-Id: Ia60f8b23b961e4132efece1e7e38f0d63597c13b
commit 7e0d00d6cfcb3d4d0ab1dd3eeac556817735139e
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Aug 20 01:33:43 2013 +0200
Enable getmntinfo(3)
Change-Id: Id9d11a67cdcad331a52030127f7c7ead3c847919
commit 8d9632ecfc3d83be4e1b4ee256ee0388a77748f8
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Aug 20 00:49:07 2013 +0200
test55: add tests for getvfsstat(2)
Change-Id: Iad4567068a82bb0e780891a478ba5a06b63f1d48
commit 2e60389afacfce32940e330d28fffe5ed1a59eb3
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Aug 20 01:28:23 2013 +0200
Implement support for [f]statvfs1(2)
The [f]statvfs(3) calls now use [f]statvfs1(2).
Change-Id: I56c92fe1c70670f476631c4a50e47351562712c6
commit be1d453fc179741aed20bd6122b6de8b15b43f1d
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Aug 20 01:39:47 2013 +0200
Implement support for getvfsstat(2)
Change-Id: I4680c071b94fa855edfb6220b03cff6b20f3c1c9
commit 6ed7e451f149fa9e062ab66d4a976f3971dc08f1
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Aug 20 01:37:18 2013 +0200
Redo mount(2)/umount(2) ABI
- pass in file system type through mount(2), and return this type in
statvfs structures as generated by [f]statvfs(2);
- align mount flags field with NetBSD's, splitting out service flags
which are not to be passed to VFS;
- remove limitation of mount ABI to 16-byte labels, so that labels
can be made larger in the future;
- introduce new m11 message union type for mount(2) as side effect.
Change-Id: Ia9ed4566d88af5239749c57274312be26bb61448
commit 314ccf892ad9db92b26ae8f6e0a8419f9f5a18b4
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Aug 20 01:35:35 2013 +0200
Align "struct statvfs" with NetBSD
This is a requirement for implementing calls such as getmntinfo(3).
VFS is now responsible for filling in some of the structure's fields.
Change-Id: I457b463c70ea2f326b9c50de954a91cfefba0065
commit 4d748d6c8f5b4f296d6b25f042e3f312c142b3ff
Author: David van Moolenbroek <david@minix3.org>
Date: Tue Aug 20 00:55:49 2013 +0200
VFS/FS: remove fstatfs(2) and REQ_FSTATFS
The fstatfs(3) call now uses fstatvfs(2).
Change-Id: Ic6bbb040e1a8f01aaffe1a6a809dd4c7a2eae2f6
Change-Id: Ied93a28c893d639fb4d46eb6483b84219013e059
This commit is contained in:
parent
3342fb471b
commit
a037a70169
|
|
@ -1,7 +1,7 @@
|
|||
# $NetBSD: Makefile,v 1.22 2007/12/31 15:31:24 ad Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
||||
|
||||
SUBDIR= cat date echo ed expr kill ksh ln ls \
|
||||
SUBDIR= cat date df echo ed expr kill ksh ln ls \
|
||||
mkdir pax pwd rm rmdir sync test
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
|
|
|||
11
bin/df/Makefile
Normal file
11
bin/df/Makefile
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# $NetBSD: Makefile,v 1.19 2011/08/28 08:20:58 christos Exp $
|
||||
# @(#)Makefile 8.3 (Berkeley) 5/8/95
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= df
|
||||
|
||||
LDADD+=-lutil
|
||||
DPADD+=${LIBUTIL}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
206
bin/df/df.1
Normal file
206
bin/df/df.1
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
.\" $NetBSD: df.1,v 1.44 2010/04/05 21:17:28 joerg Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1989, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)df.1 8.2 (Berkeley) 1/13/92
|
||||
.\"
|
||||
.Dd March 4, 2008
|
||||
.Dt DF 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm df
|
||||
.Nd display free disk space
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl agklmn
|
||||
.Op Fl G | Fl i | Fl P
|
||||
.Op Fl t Ar type
|
||||
.Op Ar file | Ar file_system ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
displays statistics about the amount of free disk space on the specified
|
||||
.Ar file_system
|
||||
or on the file system of which
|
||||
.Ar file
|
||||
is a part.
|
||||
By default, all sizes are reported in 512-byte block counts.
|
||||
If neither a file or a
|
||||
.Ar file_system
|
||||
operand is specified,
|
||||
statistics for all mounted file systems are displayed
|
||||
(subject to the
|
||||
.Fl l
|
||||
and
|
||||
.Fl t
|
||||
options below).
|
||||
.Pp
|
||||
Note that the printed count of available blocks takes
|
||||
.Va minfree
|
||||
into account, and thus will be negative when the number of free blocks
|
||||
on the filesystem is less than
|
||||
.Va minfree .
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a
|
||||
Show all mount points,
|
||||
including those that were mounted with the
|
||||
.Dv MNT_IGNORE
|
||||
flag.
|
||||
.It Fl G
|
||||
Display all the fields of the structure(s) returned by
|
||||
.Xr statvfs 2 .
|
||||
This option cannot be used with the
|
||||
.Fl i
|
||||
or
|
||||
.Fl P
|
||||
options, and it is modelled after the Solaris
|
||||
.Fl g
|
||||
option.
|
||||
This option will override the
|
||||
.Fl g ,
|
||||
.Fl h ,
|
||||
.Fl k ,
|
||||
and
|
||||
.Fl m
|
||||
options, as well as any setting of
|
||||
.Ev BLOCKSIZE .
|
||||
.It Fl g
|
||||
The
|
||||
.Fl g
|
||||
option causes the numbers to be reported in gigabytes (1024*1024*1024
|
||||
bytes).
|
||||
.It Fl h
|
||||
"Human-readable" output.
|
||||
Use unit suffixes: Byte, Kilobyte, Megabyte,
|
||||
Gigabyte, Terabyte, Petabyte, Exabyte in order to reduce the number of
|
||||
digits to four or less.
|
||||
.It Fl i
|
||||
Include statistics on the number of free inodes.
|
||||
.It Fl k
|
||||
By default, all sizes are reported in 512-byte block counts.
|
||||
The
|
||||
.Fl k
|
||||
option causes the numbers to be reported in kilobytes (1024 bytes).
|
||||
.It Fl l
|
||||
Display statistics only about mounted file systems with the
|
||||
.Dv MNT_LOCAL
|
||||
flag set.
|
||||
If a non-local file system is given as an argument, a
|
||||
warning is issued and no information is given on that file system.
|
||||
.It Fl m
|
||||
The
|
||||
.Fl m
|
||||
option causes the numbers to be reported in megabytes (1024*1024 bytes).
|
||||
.It Fl n
|
||||
Print out the previously obtained statistics from the file systems.
|
||||
This option should be used if it is possible that one or more
|
||||
file systems are in a state such that they will not be able to provide
|
||||
statistics without a long delay.
|
||||
When this option is specified,
|
||||
.Nm
|
||||
will not request new statistics from the file systems, but will respond
|
||||
with the possibly stale statistics that were previously obtained.
|
||||
.It Fl P
|
||||
Produce output in the following portable format:
|
||||
.Pp
|
||||
If both the
|
||||
.Fl P
|
||||
and
|
||||
.Fl k
|
||||
option are specified, the output will be preceded by the following header
|
||||
line, formatted to match the data following it:
|
||||
.Bd -literal
|
||||
"Filesystem 1024-blocks Used Available Capacity Mounted on\en"
|
||||
.Ed
|
||||
.Pp
|
||||
If the
|
||||
.Fl P
|
||||
option is specified without the
|
||||
.Fl k
|
||||
options, the output will be preceded by the following header line,
|
||||
formatted to match the data following it:
|
||||
.Bd -literal
|
||||
"Filesystem \*[Lt]blksize\*[Gt]-blocks Used Available Capacity Mounted on\en"
|
||||
.Ed
|
||||
.Pp
|
||||
The header line is followed by data formatted as follows:
|
||||
.Bd -literal
|
||||
"%s %d %d %d %d%% %s\en", \*[Lt]file system name\*[Gt], \*[Lt]total space\*[Gt],
|
||||
\*[Lt]space used\*[Gt], \*[Lt]space free\*[Gt], \*[Lt]percentage used\*[Gt],
|
||||
\*[Lt]file system root\*[Gt]
|
||||
.Ed
|
||||
.Pp
|
||||
Note that the
|
||||
.Fl i
|
||||
option may not be specified with
|
||||
.Fl P .
|
||||
.It Fl t Ar type
|
||||
Is used to indicate the actions should only be taken on
|
||||
filesystems of the specified type.
|
||||
More than one type may be specified in a comma-separated list.
|
||||
The list of filesystem types can be prefixed with
|
||||
.Dq no
|
||||
to specify the filesystem types for which action should
|
||||
.Em not
|
||||
be taken.
|
||||
If a file system is given on the command line that is not of
|
||||
the specified type, a warning is issued and no information is given on
|
||||
that file system.
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width BLOCKSIZE
|
||||
.It Ev BLOCKSIZE
|
||||
If the environment variable
|
||||
.Ev BLOCKSIZE
|
||||
is set, and the
|
||||
.Fl g ,
|
||||
.Fl h ,
|
||||
.Fl k
|
||||
and
|
||||
.Fl m
|
||||
options are not specified, the block counts will be displayed in units of that
|
||||
size block.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr quota 1 ,
|
||||
.Xr fstatvfs 2 ,
|
||||
.Xr getvfsstat 2 ,
|
||||
.Xr statvfs 2 ,
|
||||
.Xr getbsize 3 ,
|
||||
.Xr getmntinfo 3 ,
|
||||
.Xr fs 5 ,
|
||||
.Xr fstab 5 ,
|
||||
.Xr mount 8 ,
|
||||
.Xr quot 8 ,
|
||||
.Xr tunefs 8
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v6 .
|
||||
520
bin/df/df.c
Normal file
520
bin/df/df.c
Normal file
|
|
@ -0,0 +1,520 @@
|
|||
/* $NetBSD: df.c,v 1.90 2012/01/07 18:45:13 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT(
|
||||
"@(#) Copyright (c) 1980, 1990, 1993, 1994\
|
||||
The Regents of the University of California. All rights reserved.");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)df.c 8.7 (Berkeley) 4/2/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: df.c,v 1.90 2012/01/07 18:45:13 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <util.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <util.h>
|
||||
|
||||
static char *getmntpt(const char *);
|
||||
static void prtstat(struct statvfs *, int);
|
||||
static int selected(const char *, size_t);
|
||||
static void maketypelist(char *);
|
||||
static size_t regetmntinfo(struct statvfs **, size_t);
|
||||
__dead static void usage(void);
|
||||
static void prthumanval(int64_t, const char *);
|
||||
static void prthuman(struct statvfs *, int64_t, int64_t);
|
||||
|
||||
static int aflag, gflag, hflag, iflag, lflag, nflag, Pflag;
|
||||
static long usize;
|
||||
static char **typelist;
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct stat stbuf;
|
||||
struct statvfs *mntbuf;
|
||||
long mntsize;
|
||||
int ch, i, maxwidth, width;
|
||||
char *mntpt;
|
||||
|
||||
setprogname(argv[0]);
|
||||
(void)setlocale(LC_ALL, "");
|
||||
|
||||
while ((ch = getopt(argc, argv, "aGghiklmnPt:")) != -1)
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
aflag = 1;
|
||||
break;
|
||||
case 'g':
|
||||
hflag = 0;
|
||||
usize = 1024 * 1024 * 1024;
|
||||
break;
|
||||
case 'G':
|
||||
gflag = 1;
|
||||
break;
|
||||
case 'h':
|
||||
hflag = 1;
|
||||
usize = 0;
|
||||
break;
|
||||
case 'i':
|
||||
iflag = 1;
|
||||
break;
|
||||
case 'k':
|
||||
hflag = 0;
|
||||
usize = 1024;
|
||||
break;
|
||||
case 'l':
|
||||
lflag = 1;
|
||||
break;
|
||||
case 'm':
|
||||
hflag = 0;
|
||||
usize = 1024 * 1024;
|
||||
break;
|
||||
case 'n':
|
||||
nflag = 1;
|
||||
break;
|
||||
case 'P':
|
||||
Pflag = 1;
|
||||
break;
|
||||
case 't':
|
||||
if (typelist != NULL)
|
||||
errx(EXIT_FAILURE,
|
||||
"only one -t option may be specified.");
|
||||
maketypelist(optarg);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
if (gflag && (Pflag || iflag))
|
||||
errx(EXIT_FAILURE,
|
||||
"only one of -G and -P or -i may be specified");
|
||||
if (Pflag && iflag)
|
||||
errx(EXIT_FAILURE,
|
||||
"only one of -P and -i may be specified");
|
||||
#if 0
|
||||
/*
|
||||
* The block size cannot be checked until after getbsize() is called.
|
||||
*/
|
||||
if (Pflag && (hflag || (usize != 1024 && usize != 512)))
|
||||
errx(EXIT_FAILURE,
|
||||
"non-standard block size incompatible with -P");
|
||||
#endif
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
|
||||
if (mntsize == 0)
|
||||
err(EXIT_FAILURE,
|
||||
"retrieving information on mounted file systems");
|
||||
|
||||
if (*argv == NULL) {
|
||||
mntsize = regetmntinfo(&mntbuf, mntsize);
|
||||
} else {
|
||||
if ((mntbuf = malloc(argc * sizeof(*mntbuf))) == NULL)
|
||||
err(EXIT_FAILURE, "can't allocate statvfs array");
|
||||
mntsize = 0;
|
||||
for (/*EMPTY*/; *argv != NULL; argv++) {
|
||||
if (stat(*argv, &stbuf) < 0) {
|
||||
if ((mntpt = getmntpt(*argv)) == 0) {
|
||||
warn("%s", *argv);
|
||||
continue;
|
||||
}
|
||||
} else if (S_ISBLK(stbuf.st_mode)) {
|
||||
if ((mntpt = getmntpt(*argv)) == 0)
|
||||
mntpt = *argv;
|
||||
} else
|
||||
mntpt = *argv;
|
||||
/*
|
||||
* Statfs does not take a `wait' flag, so we cannot
|
||||
* implement nflag here.
|
||||
*/
|
||||
if (!statvfs(mntpt, &mntbuf[mntsize]))
|
||||
if (lflag &&
|
||||
(mntbuf[mntsize].f_flag & MNT_LOCAL) == 0)
|
||||
warnx("Warning: %s is not a local %s",
|
||||
*argv, "file system");
|
||||
else if
|
||||
(!selected(mntbuf[mntsize].f_fstypename,
|
||||
sizeof(mntbuf[mntsize].f_fstypename)))
|
||||
warnx("Warning: %s mounted as a %s %s",
|
||||
*argv,
|
||||
mntbuf[mntsize].f_fstypename,
|
||||
"file system");
|
||||
else
|
||||
++mntsize;
|
||||
else
|
||||
warn("%s", *argv);
|
||||
}
|
||||
}
|
||||
|
||||
maxwidth = 0;
|
||||
for (i = 0; i < mntsize; i++) {
|
||||
width = (int)strlen(mntbuf[i].f_mntfromname);
|
||||
if (width > maxwidth)
|
||||
maxwidth = width;
|
||||
}
|
||||
for (i = 0; i < mntsize; i++)
|
||||
prtstat(&mntbuf[i], maxwidth);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
getmntpt(const char *name)
|
||||
{
|
||||
size_t mntsize, i;
|
||||
struct statvfs *mntbuf;
|
||||
|
||||
mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
|
||||
if (mntsize == 0)
|
||||
err(EXIT_FAILURE, "Can't get mount information");
|
||||
for (i = 0; i < mntsize; i++) {
|
||||
if (!strcmp(mntbuf[i].f_mntfromname, name))
|
||||
return mntbuf[i].f_mntonname;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum { IN_LIST, NOT_IN_LIST } which;
|
||||
|
||||
static int
|
||||
selected(const char *type, size_t len)
|
||||
{
|
||||
char **av;
|
||||
|
||||
/* If no type specified, it's always selected. */
|
||||
if (typelist == NULL)
|
||||
return 1;
|
||||
for (av = typelist; *av != NULL; ++av)
|
||||
if (!strncmp(type, *av, len))
|
||||
return which == IN_LIST ? 1 : 0;
|
||||
return which == IN_LIST ? 0 : 1;
|
||||
}
|
||||
|
||||
static void
|
||||
maketypelist(char *fslist)
|
||||
{
|
||||
size_t i;
|
||||
char *nextcp, **av;
|
||||
|
||||
if ((fslist == NULL) || (fslist[0] == '\0'))
|
||||
errx(EXIT_FAILURE, "empty type list");
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Note: the syntax is "noxxx,yyy" for no xxx's and
|
||||
* no yyy's, not the more intuitive "noyyy,noyyy".
|
||||
*/
|
||||
if (fslist[0] == 'n' && fslist[1] == 'o') {
|
||||
fslist += 2;
|
||||
which = NOT_IN_LIST;
|
||||
} else
|
||||
which = IN_LIST;
|
||||
|
||||
/* Count the number of types. */
|
||||
for (i = 1, nextcp = fslist;
|
||||
(nextcp = strchr(nextcp, ',')) != NULL; i++)
|
||||
++nextcp;
|
||||
|
||||
/* Build an array of that many types. */
|
||||
if ((av = typelist = malloc((i + 1) * sizeof(*av))) == NULL)
|
||||
err(EXIT_FAILURE, "can't allocate type array");
|
||||
av[0] = fslist;
|
||||
for (i = 1, nextcp = fslist;
|
||||
(nextcp = strchr(nextcp, ',')) != NULL; i++) {
|
||||
*nextcp = '\0';
|
||||
av[i] = ++nextcp;
|
||||
}
|
||||
/* Terminate the array. */
|
||||
av[i] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a pass over the filesystem info in ``mntbuf'' filtering out
|
||||
* filesystem types not in ``fsmask'' and possibly re-stating to get
|
||||
* current (not cached) info. Returns the new count of valid statvfs bufs.
|
||||
*/
|
||||
static size_t
|
||||
regetmntinfo(struct statvfs **mntbufp, size_t mntsize)
|
||||
{
|
||||
size_t i, j;
|
||||
struct statvfs *mntbuf;
|
||||
|
||||
if (!lflag && typelist == NULL && aflag)
|
||||
return nflag ? mntsize : (size_t)getmntinfo(mntbufp, MNT_WAIT);
|
||||
|
||||
mntbuf = *mntbufp;
|
||||
j = 0;
|
||||
for (i = 0; i < mntsize; i++) {
|
||||
if (!aflag && (mntbuf[i].f_flag & MNT_IGNORE) != 0)
|
||||
continue;
|
||||
if (lflag && (mntbuf[i].f_flag & MNT_LOCAL) == 0)
|
||||
continue;
|
||||
if (!selected(mntbuf[i].f_fstypename,
|
||||
sizeof(mntbuf[i].f_fstypename)))
|
||||
continue;
|
||||
if (nflag)
|
||||
mntbuf[j] = mntbuf[i];
|
||||
else {
|
||||
struct statvfs layerbuf = mntbuf[i];
|
||||
(void)statvfs(mntbuf[i].f_mntonname, &mntbuf[j]);
|
||||
/*
|
||||
* If the FS name changed, then new data is for
|
||||
* a different layer and we don't want it.
|
||||
*/
|
||||
if (memcmp(layerbuf.f_mntfromname,
|
||||
mntbuf[j].f_mntfromname, MNAMELEN))
|
||||
mntbuf[j] = layerbuf;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
static void
|
||||
prthumanval(int64_t bytes, const char *pad)
|
||||
{
|
||||
char buf[6];
|
||||
|
||||
(void)humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1),
|
||||
bytes, "", HN_AUTOSCALE,
|
||||
HN_B | HN_NOSPACE | HN_DECIMAL);
|
||||
|
||||
(void)printf("%s %6s", pad, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
prthuman(struct statvfs *sfsp, int64_t used, int64_t bavail)
|
||||
{
|
||||
|
||||
prthumanval((int64_t)(sfsp->f_blocks * sfsp->f_frsize), " ");
|
||||
prthumanval((int64_t)(used * sfsp->f_frsize), " ");
|
||||
prthumanval((int64_t)(bavail * sfsp->f_frsize), " ");
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert statvfs returned filesystem size into BLOCKSIZE units.
|
||||
* Attempts to avoid overflow for large filesystems.
|
||||
*/
|
||||
#define fsbtoblk(num, fsbs, bs) \
|
||||
(((fsbs) != 0 && (uint64_t)(fsbs) < (uint64_t)(bs)) ? \
|
||||
(int64_t)(num) / (int64_t)((bs) / (fsbs)) : \
|
||||
(int64_t)(num) * (int64_t)((fsbs) / (bs)))
|
||||
|
||||
/*
|
||||
* Print out status about a filesystem.
|
||||
*/
|
||||
static void
|
||||
prtstat(struct statvfs *sfsp, int maxwidth)
|
||||
{
|
||||
static long blocksize;
|
||||
static int headerlen, timesthrough;
|
||||
static const char *header;
|
||||
static const char full[] = "100";
|
||||
static const char empty[] = " 0";
|
||||
int64_t used, availblks, inodes;
|
||||
int64_t bavail;
|
||||
char pb[64];
|
||||
|
||||
if (gflag) {
|
||||
/*
|
||||
* From SunOS-5.6:
|
||||
*
|
||||
* /var (/dev/dsk/c0t0d0s3 ): 8192 block size 1024 frag size
|
||||
* 984242 total blocks 860692 free blocks 859708 available 249984 total files
|
||||
* 248691 free files 8388611 filesys id
|
||||
* ufs fstype 0x00000004 flag 255 filename length
|
||||
*
|
||||
*/
|
||||
(void)printf("%10s (%-12s): %7ld block size %12ld frag size\n",
|
||||
sfsp->f_mntonname, sfsp->f_mntfromname,
|
||||
sfsp->f_iosize, /* On UFS/FFS systems this is
|
||||
* also called the "optimal
|
||||
* transfer block size" but it
|
||||
* is of course the file
|
||||
* system's block size too.
|
||||
*/
|
||||
sfsp->f_bsize); /* not so surprisingly the
|
||||
* "fundamental file system
|
||||
* block size" is the frag
|
||||
* size.
|
||||
*/
|
||||
(void)printf("%10" PRId64 " total blocks %10" PRId64
|
||||
" free blocks %10" PRId64 " available\n",
|
||||
(uint64_t)sfsp->f_blocks, (uint64_t)sfsp->f_bfree,
|
||||
(uint64_t)sfsp->f_bavail);
|
||||
(void)printf("%10" PRId64 " total files %10" PRId64
|
||||
" free files %12lx filesys id\n",
|
||||
(uint64_t)sfsp->f_ffree, (uint64_t)sfsp->f_files,
|
||||
sfsp->f_fsid);
|
||||
(void)printf("%10s fstype %#15lx flag %17ld filename "
|
||||
"length\n", sfsp->f_fstypename, sfsp->f_flag,
|
||||
sfsp->f_namemax);
|
||||
(void)printf("%10lu owner %17" PRId64 " syncwrites %12" PRId64
|
||||
" asyncwrites\n\n", (unsigned long)sfsp->f_owner,
|
||||
sfsp->f_syncwrites, sfsp->f_asyncwrites);
|
||||
|
||||
/*
|
||||
* a concession by the structured programming police to the
|
||||
* indentation police....
|
||||
*/
|
||||
return;
|
||||
}
|
||||
if (maxwidth < 12)
|
||||
maxwidth = 12;
|
||||
if (++timesthrough == 1) {
|
||||
switch (blocksize = usize) {
|
||||
case 1024:
|
||||
header = Pflag ? "1024-blocks" : "1K-blocks";
|
||||
headerlen = (int)strlen(header);
|
||||
break;
|
||||
case 1024 * 1024:
|
||||
header = "1M-blocks";
|
||||
headerlen = (int)strlen(header);
|
||||
break;
|
||||
case 1024 * 1024 * 1024:
|
||||
header = "1G-blocks";
|
||||
headerlen = (int)strlen(header);
|
||||
break;
|
||||
default:
|
||||
if (hflag) {
|
||||
header = "Size";
|
||||
headerlen = (int)strlen(header);
|
||||
} else
|
||||
header = getbsize(&headerlen, &blocksize);
|
||||
break;
|
||||
}
|
||||
if (Pflag) {
|
||||
/*
|
||||
* either:
|
||||
* "Filesystem 1024-blocks Used Available Capacity Mounted on\n"
|
||||
* or:
|
||||
* "Filesystem 512-blocks Used Available Capacity Mounted on\n"
|
||||
*/
|
||||
if (blocksize != 1024 && blocksize != 512)
|
||||
errx(EXIT_FAILURE,
|
||||
"non-standard block size incompatible with -P");
|
||||
(void)printf("Filesystem %s Used Available Capacity "
|
||||
"Mounted on\n", header);
|
||||
} else {
|
||||
(void)printf("%-*.*s %s Used Avail %%Cap",
|
||||
maxwidth - (headerlen - 10),
|
||||
maxwidth - (headerlen - 10),
|
||||
"Filesystem", header);
|
||||
if (iflag)
|
||||
(void)printf(" iUsed iAvail %%iCap");
|
||||
(void)printf(" Mounted on\n");
|
||||
}
|
||||
}
|
||||
used = sfsp->f_blocks - sfsp->f_bfree;
|
||||
bavail = sfsp->f_bfree - sfsp->f_bresvd;
|
||||
availblks = bavail + used;
|
||||
if (Pflag) {
|
||||
assert(hflag == 0);
|
||||
assert(blocksize > 0);
|
||||
/*
|
||||
* "%s %d %d %d %s %s\n", <file system name>, <total space>,
|
||||
* <space used>, <space free>, <percentage used>,
|
||||
* <file system root>
|
||||
*/
|
||||
(void)printf("%s %" PRId64 " %" PRId64 " %" PRId64 " %s%% %s\n",
|
||||
sfsp->f_mntfromname,
|
||||
fsbtoblk(sfsp->f_blocks, sfsp->f_frsize, blocksize),
|
||||
fsbtoblk(used, sfsp->f_frsize, blocksize),
|
||||
fsbtoblk(bavail, sfsp->f_frsize, blocksize),
|
||||
availblks == 0 ? full : strspct(pb, sizeof(pb), used,
|
||||
availblks, 0), sfsp->f_mntonname);
|
||||
/*
|
||||
* another concession by the structured programming police to
|
||||
* the indentation police....
|
||||
*
|
||||
* Note iflag cannot be set when Pflag is set.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
(void)printf("%-*.*s ", maxwidth, maxwidth, sfsp->f_mntfromname);
|
||||
|
||||
if (hflag)
|
||||
prthuman(sfsp, used, bavail);
|
||||
else
|
||||
(void)printf("%10" PRId64 " %10" PRId64 " %10" PRId64,
|
||||
fsbtoblk(sfsp->f_blocks, sfsp->f_frsize, blocksize),
|
||||
fsbtoblk(used, sfsp->f_frsize, blocksize),
|
||||
fsbtoblk(bavail, sfsp->f_frsize, blocksize));
|
||||
(void)printf(" %3s%%",
|
||||
availblks == 0 ? full :
|
||||
strspct(pb, sizeof(pb), used, availblks, 0));
|
||||
if (iflag) {
|
||||
inodes = sfsp->f_files;
|
||||
used = inodes - sfsp->f_ffree;
|
||||
(void)printf(" %8jd %8jd %3s%%",
|
||||
(intmax_t)used, (intmax_t)sfsp->f_ffree,
|
||||
inodes == 0 ? (used == 0 ? empty : full) :
|
||||
strspct(pb, sizeof(pb), used, inodes, 0));
|
||||
}
|
||||
(void)printf(" %s\n", sfsp->f_mntonname);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
(void)fprintf(stderr,
|
||||
"Usage: %s [-aGgln] [-hkm|-ihkm|-Pk] [-t type] [file | "
|
||||
"file_system ...]\n",
|
||||
getprogname());
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
|
@ -196,6 +196,22 @@ do
|
|||
18,0)
|
||||
des="UNIX domain socket" dev=uds
|
||||
;;
|
||||
5[6-9],0|6[0-3],0)
|
||||
drive=`expr $major - 56`
|
||||
des="vnode disk $drive" dev=vnd$drive
|
||||
;;
|
||||
5[6-9],[1-4]|6[0-3],[1-4])
|
||||
drive=`expr $major - 56`
|
||||
par=`expr $minor - 1`
|
||||
des="vnode disk $drive partition $par" dev=vnd${drive}p${par}
|
||||
;;
|
||||
5[6-9],12[89]|5[6-9],13[0-9]|5[6-9],14[0-3]|6[0-3],12[89]|5[6-9],13[0-9]|5[6-9],14[0-3])
|
||||
drive=`expr $major - 56`
|
||||
par=`expr \\( \\( $minor - 128 \\) / 4 \\) % 4`
|
||||
sub=`expr \\( $minor - 128 \\) % 4`
|
||||
des="vnode disk $drive partition $par slice $sub"
|
||||
dev=vnd${drive}p${par}s${sub}
|
||||
;;
|
||||
BAD,BAD)
|
||||
des= dev=
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,9 @@ case $#:$1 in
|
|||
eepromb3s54 eepromb3s55 eepromb3s56 eepromb3s57 \
|
||||
tsl2550b1s39 tsl2550b2s39 tsl2550b3s39 \
|
||||
sht21b1s40 sht21b2s40 sht21b3s40 \
|
||||
bmp085b1s77 bmp085b2s77 bmp085b3s77
|
||||
bmp085b1s77 bmp085b2s77 bmp085b3s77 \
|
||||
vnd0 vnd0p0 vnd0p0s0 vnd1 vnd1p0 vnd1p0s0 \
|
||||
vnd2 vnd3 vnd4 vnd5 vnd6 vnd7
|
||||
;;
|
||||
0:|1:-\?)
|
||||
cat >&2 <<EOF
|
||||
|
|
@ -67,6 +69,7 @@ Where key is one of the following:
|
|||
fbd # Make /dev/fbd
|
||||
hello # Make /dev/hello
|
||||
video # Make /dev/video
|
||||
vnd0 vnd0p0 vnd0p0s0 .. # Make vnode disks /dev/vnd[0-7] and (sub)partitions
|
||||
std # All standard devices
|
||||
EOF
|
||||
exit 1
|
||||
|
|
@ -331,6 +334,46 @@ do
|
|||
$e mknod bmp085b${b}s77 c ${m} 0
|
||||
$e chmod 444 bmp085b${b}s77
|
||||
;;
|
||||
vnd[0-7])
|
||||
# Whole vnode disk devices.
|
||||
d=`expr $dev : 'vnd\\(.\\)'` # Disk number.
|
||||
maj=`expr $d + 56` # Major device number.
|
||||
$e mknod $dev b $maj 0
|
||||
$e chmod 600 $dev
|
||||
;;
|
||||
vnd[0-7]p[0-3])
|
||||
# Vnode disk primary partitions.
|
||||
n=`expr $dev : '\\(.*\\).'` # Name prefix.
|
||||
d=`expr $dev : 'vnd\\(.\\)'` # Disk number.
|
||||
maj=`expr $d + 56` # Major device number.
|
||||
alldev=
|
||||
|
||||
for p in 0 1 2 3
|
||||
do
|
||||
m=`expr 1 + $p` # Minor device number.
|
||||
$e mknod $n$p b $maj $m
|
||||
alldev="$alldev $n$p"
|
||||
done
|
||||
echo $alldev | xargs $e chmod 600
|
||||
;;
|
||||
vnd[0-7]p[0-3]s[0-3])
|
||||
# Vnode disk subpartition.
|
||||
n=`expr $dev : '\\(.*\\)...'` # Name prefix.
|
||||
d=`expr $dev : 'vnd\\(.\\)'` # Disk number.
|
||||
maj=`expr $d + 56` # Major device number.
|
||||
alldev=
|
||||
|
||||
for p in 0 1 2 3
|
||||
do
|
||||
for s in 0 1 2 3
|
||||
do
|
||||
m=`expr 128 + $p '*' 4 + $s` # Minor device number.
|
||||
$e mknod ${n}${p}s${s} b $maj $m
|
||||
alldev="$alldev ${n}${p}s${s}"
|
||||
done
|
||||
done
|
||||
echo $alldev | xargs $e chmod 600
|
||||
;;
|
||||
*)
|
||||
echo "$0: don't know about $dev" >&2
|
||||
ex=1
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ SUBDIR= add_route arp ash at backup btrace \
|
|||
cawf cd cdprobe cpp \
|
||||
chmod chown ci cleantmp cmp co \
|
||||
comm compress cp crc cron crontab cut \
|
||||
dd decomp16 DESCRIBE devmand devsize df dhcpd \
|
||||
dhrystone diff diskctl dumpcore \
|
||||
dd decomp16 DESCRIBE devmand devsize dhcpd \
|
||||
dhrystone diff diskctl \
|
||||
eject env factor fbdctl \
|
||||
find fix fold format fortune fsck.mfs \
|
||||
gcore gcov-pull getty grep hexdump host \
|
||||
gcov-pull getty grep hexdump host \
|
||||
hostaddr id ifconfig ifdef \
|
||||
intr ipcrm ipcs irdpd isoread last \
|
||||
less loadkeys loadramdisk logger look lp \
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
PROG= df
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
237
commands/df/df.c
237
commands/df/df.c
|
|
@ -1,237 +0,0 @@
|
|||
/* df - disk free block printout Author: Andy Tanenbaum
|
||||
*
|
||||
* 91/04/30 Kees J. Bot (kjb@cs.vu.nl)
|
||||
* Map filename arguments to the devices they live on.
|
||||
* Changed output to show percentages.
|
||||
*
|
||||
* 92/12/12 Kees J. Bot
|
||||
* Posixized. (Almost, the normal output is in kilobytes, it should
|
||||
* be 512-byte units. 'df -P' and 'df -kP' are as it should be.)
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <minix/minlib.h>
|
||||
|
||||
struct mtab { /* List of mounted devices from /etc/mtab. */
|
||||
struct mtab *next;
|
||||
dev_t device;
|
||||
char *devname;
|
||||
char *mountpoint;
|
||||
} *mtab= NULL;
|
||||
|
||||
struct mtab *searchtab(char *name);
|
||||
static void readmtab(const char *type);
|
||||
int df(const struct mtab *mt);
|
||||
|
||||
int iflag= 0; /* Focus on inodes instead of blocks. */
|
||||
int Pflag= 0; /* Posix standard output. */
|
||||
int kflag= 0; /* Output in kilobytes instead of 512 byte units for -P. */
|
||||
int istty; /* isatty(1) */
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: df [-ikP] [-t type] [device]...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int unitsize;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
struct mtab *mt;
|
||||
char *type= "dev";
|
||||
int ex= 0;
|
||||
|
||||
while (argc > 1 && argv[1][0] == '-') {
|
||||
char *opt= argv[1]+1;
|
||||
|
||||
while (*opt != 0) {
|
||||
switch (*opt++) {
|
||||
case 'i': iflag= 1; break;
|
||||
case 'k': kflag= 1; break;
|
||||
case 'P': Pflag= 1; break;
|
||||
case 't':
|
||||
if (argc < 3) usage();
|
||||
type= argv[2];
|
||||
argv++;
|
||||
argc--;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
istty= isatty(1);
|
||||
|
||||
readmtab(type);
|
||||
|
||||
if(!Pflag || (Pflag && kflag)) unitsize = 1024;
|
||||
else unitsize = 512;
|
||||
|
||||
if (Pflag) {
|
||||
if (!iflag)
|
||||
printf("\
|
||||
Filesystem %4d-blocks Used Available Capacity Mounted on\n",
|
||||
unitsize);
|
||||
else
|
||||
printf("\
|
||||
Filesystem Inodes IUsed IFree %%IUsed Mounted on\n"
|
||||
);
|
||||
} else {
|
||||
printf("%s\n", !iflag ? "\
|
||||
Filesystem Size (kB) Free Used % Files% Mounted on" : "\
|
||||
Filesystem Files Free Used % BUsed% Mounted on"
|
||||
);
|
||||
}
|
||||
|
||||
if (argc == 1) {
|
||||
for (mt= mtab; mt != NULL; mt= mt->next) ex |= df(mt);
|
||||
} else {
|
||||
for (i = 1; i < argc; i++) ex |= df(searchtab(argv[i]));
|
||||
}
|
||||
exit(ex);
|
||||
}
|
||||
|
||||
static void readmtab(const char *type)
|
||||
/* Turn the mounted file table into a list. */
|
||||
{
|
||||
struct mtab **amt= &mtab, *new;
|
||||
struct stat st;
|
||||
char devname[PATH_MAX], mountpoint[PATH_MAX], version[MNTNAMELEN],
|
||||
rw_flag[MNTFLAGLEN];
|
||||
|
||||
if (load_mtab("df") < 0) exit(1);
|
||||
|
||||
while (get_mtab_entry(devname, mountpoint, version, rw_flag),
|
||||
devname[0] != 0) {
|
||||
if (strcmp(type, "dev") != 0 && strcmp(type, version) != 0) continue;
|
||||
|
||||
/* Make new list cell. */
|
||||
if ((new= (struct mtab *) malloc(sizeof(*new))) == NULL
|
||||
|| (new->devname= (char *) malloc(strlen(devname) + 1)) == NULL
|
||||
|| (new->mountpoint= (char *) malloc(strlen(mountpoint) + 1)) == NULL
|
||||
) break;
|
||||
|
||||
if (strcmp(devname, "none") != 0 && stat(devname, &st) == 0 &&
|
||||
S_ISBLK(st.st_mode)) {
|
||||
new->device= st.st_rdev;
|
||||
} else if (stat(mountpoint, &st) == 0) {
|
||||
new->device= st.st_dev;
|
||||
}
|
||||
strcpy(new->devname, devname);
|
||||
strcpy(new->mountpoint, mountpoint);
|
||||
|
||||
*amt= new; /* Add the cell to the end. */
|
||||
amt= &new->next;
|
||||
*amt= NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct mtab *searchtab(char *name)
|
||||
/* See what we can do with a user supplied name, there are three possibilities:
|
||||
* 1. It's a device and it is in the mtab: Return mtab entry.
|
||||
* 2. It's a file and lives on a device in the mtab: Return mtab entry.
|
||||
* 3. It's anything else: Return something df() will choke on.
|
||||
*/
|
||||
{
|
||||
static struct mtab unknown;
|
||||
struct mtab *mt;
|
||||
struct stat st;
|
||||
|
||||
unknown.devname= name;
|
||||
unknown.mountpoint= "";
|
||||
|
||||
if (stat(name, &st) < 0) return &unknown; /* Case 3. */
|
||||
|
||||
unknown.device= S_ISBLK(st.st_mode) ? st.st_rdev : st.st_dev;
|
||||
|
||||
for (mt= mtab; mt != NULL; mt= mt->next) {
|
||||
if (unknown.device == mt->device)
|
||||
return mt; /* Case 1 & 2. */
|
||||
}
|
||||
|
||||
return &unknown; /* Case 3. */
|
||||
}
|
||||
|
||||
/* (num / tot) in percentages rounded up. */
|
||||
#define percent(num, tot) \
|
||||
((tot > 0) ? ((int) ((100ULL * (num) + ((tot) - 1)) / (tot))) : 0)
|
||||
|
||||
int df(const struct mtab *mt)
|
||||
{
|
||||
long totblocks, busyblocks, totinodes, busyinodes;
|
||||
struct statvfs sv;
|
||||
int n;
|
||||
|
||||
if (statvfs(mt->mountpoint, &sv) < 0) {
|
||||
fprintf(stderr, "df: %s: %s\n", mt->devname, strerror(errno));
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* Print results. */
|
||||
printf("%s", mt->devname);
|
||||
n= strlen(mt->devname);
|
||||
if (n > 15 && istty) { putchar('\n'); n= 0; }
|
||||
while (n < 15) { putchar(' '); n++; }
|
||||
|
||||
totblocks = sv.f_blocks;
|
||||
busyblocks = sv.f_blocks - sv.f_bfree;
|
||||
|
||||
busyblocks = busyblocks * (sv.f_bsize/512) / (unitsize/512);
|
||||
totblocks = totblocks * (sv.f_bsize/512) / (unitsize/512);
|
||||
|
||||
totinodes = sv.f_files;
|
||||
busyinodes = sv.f_files - sv.f_ffree;
|
||||
|
||||
if (!Pflag && !iflag) {
|
||||
printf(" %9ld %9ld %9ld %3d%% %3d%% %s\n",
|
||||
totblocks, /* Blocks */
|
||||
totblocks - busyblocks, /* free */
|
||||
busyblocks, /* used */
|
||||
percent(busyblocks, totblocks), /* % */
|
||||
percent(busyinodes, totinodes), /* FUsed% */
|
||||
mt->mountpoint /* Mounted on */
|
||||
);
|
||||
}
|
||||
if (!Pflag && iflag) {
|
||||
printf(" %9ld %9ld %9ld %3d%% %3d%% %s\n",
|
||||
totinodes, /* Files */
|
||||
totinodes - busyinodes, /* free */
|
||||
busyinodes, /* used */
|
||||
percent(busyinodes, totinodes), /* % */
|
||||
percent(busyblocks, totblocks), /* BUsed% */
|
||||
mt->mountpoint /* Mounted on */
|
||||
);
|
||||
}
|
||||
if (Pflag && !iflag) {
|
||||
printf(" %9ld %9ld %9ld %4d%% %s\n",
|
||||
totblocks, /* Blocks */
|
||||
busyblocks, /* Used */
|
||||
totblocks - busyblocks, /* Available */
|
||||
percent(busyblocks, totblocks), /* Capacity */
|
||||
mt->mountpoint /* Mounted on */
|
||||
);
|
||||
}
|
||||
if (Pflag && iflag) {
|
||||
printf(" %9ld %9ld %9ld %4d%% %s\n",
|
||||
totinodes, /* Inodes */
|
||||
busyinodes, /* IUsed */
|
||||
totinodes - busyinodes, /* IAvail */
|
||||
percent(busyinodes, totinodes), /* Capacity */
|
||||
mt->mountpoint /* Mounted on */
|
||||
);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
PROG= dumpcore
|
||||
CPPFLAGS+= -I${NETBSDSRCDIR}
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/* dumpcore - create core file of running process */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <minix/config.h>
|
||||
#include <minix/type.h>
|
||||
#include <minix/ipc.h>
|
||||
#include <minix/const.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <timers.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <machine/archtypes.h>
|
||||
#include "kernel/proc.h"
|
||||
|
||||
#define CLICK_WORDS (CLICK_SIZE / sizeof(unsigned long))
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
pid_t pid;
|
||||
int r, status;
|
||||
|
||||
if(argc != 2) {
|
||||
printf("usage: %s <pid>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pid = atoi(argv[1]);
|
||||
|
||||
if (ptrace(T_ATTACH, pid, 0, 0) != 0) {
|
||||
perror("ptrace(T_ATTACH)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (waitpid(pid, &status, 0) != pid) {
|
||||
perror("waitpid");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (WIFSTOPPED(status) && WSTOPSIG(status) != SIGSTOP) {
|
||||
/* whatever happens here is fine */
|
||||
ptrace(T_RESUME, pid, 0, WSTOPSIG(status));
|
||||
|
||||
if (waitpid(pid, &status, 0) != pid) {
|
||||
perror("waitpid");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WIFSTOPPED(status)) {
|
||||
fprintf(stderr, "process died while attaching\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ptrace(T_DUMPCORE, pid, 0, 0) != 0) {
|
||||
fprintf(stderr, "warning, dumpcore failed (%s)\n",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
if (ptrace(T_DETACH, pid, 0, 0)) {
|
||||
fprintf(stderr, "warning, detaching failed (%s)\n",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
@ -75,7 +75,7 @@ char *secbuf;
|
|||
int badbases;
|
||||
int badsizes;
|
||||
int badorders;
|
||||
char *devname;
|
||||
char *dev_name;
|
||||
int nhead;
|
||||
int nsec;
|
||||
int ncyl = 1024;
|
||||
|
|
@ -161,9 +161,9 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
if (argn == argc)
|
||||
devname = DEFAULT_DEV;
|
||||
dev_name = DEFAULT_DEV;
|
||||
else if (argn == argc - 1)
|
||||
devname = argv[argn];
|
||||
dev_name = argv[argn];
|
||||
else
|
||||
usage();
|
||||
|
||||
|
|
@ -232,7 +232,7 @@ void getgeom(void)
|
|||
|
||||
if (override) return;
|
||||
|
||||
if ((fd= open(devname, O_RDONLY)) < 0) return;
|
||||
if ((fd= open(dev_name, O_RDONLY)) < 0) return;
|
||||
|
||||
r = ioctl(fd, DIOCGETP, &geom);
|
||||
close(fd);
|
||||
|
|
@ -242,21 +242,21 @@ void getgeom(void)
|
|||
nsec = geom.sectors;
|
||||
ncyl = geom.cylinders;
|
||||
|
||||
printf("Geometry of %s: %dx%dx%d\n", devname, ncyl, nhead, nsec);
|
||||
printf("Geometry of %s: %dx%dx%d\n", dev_name, ncyl, nhead, nsec);
|
||||
}
|
||||
|
||||
static int devfd;
|
||||
|
||||
void getboot(char *buffer)
|
||||
{
|
||||
devfd = open(devname, 2);
|
||||
devfd = open(dev_name, 2);
|
||||
if (devfd < 0) {
|
||||
printf("No write permission on %s\n", devname);
|
||||
printf("No write permission on %s\n", dev_name);
|
||||
readonly = 1;
|
||||
devfd = open(devname, 0);
|
||||
devfd = open(dev_name, 0);
|
||||
}
|
||||
if (devfd < 0) {
|
||||
printf("Cannot open device %s\n", devname);
|
||||
printf("Cannot open device %s\n", dev_name);
|
||||
exit(1);
|
||||
}
|
||||
if (read(devfd, buffer, SECSIZE) != SECSIZE) {
|
||||
|
|
@ -264,7 +264,7 @@ void getboot(char *buffer)
|
|||
exit(1);
|
||||
}
|
||||
if (* (unsigned short *) &buffer[510] != 0xAA55) {
|
||||
printf("Invalid boot sector on %s.\n", devname);
|
||||
printf("Invalid boot sector on %s.\n", dev_name);
|
||||
printf("Partition table reset and boot code installed.\n");
|
||||
memset(buffer, 0, 512);
|
||||
memcpy(buffer, bootstrap, sizeof(bootstrap));
|
||||
|
|
@ -514,8 +514,8 @@ int chk_table(void)
|
|||
printf(
|
||||
"Disk appears to have mis-specified number of heads or sectors.\n");
|
||||
printf("Try fdisk -h%d -s%d %s instead of\n",
|
||||
maxhead + 1, maxsec, devname);
|
||||
printf(" fdisk -h%d -s%d %s\n", nhead, nsec, devname);
|
||||
maxhead + 1, maxsec, dev_name);
|
||||
printf(" fdisk -h%d -s%d %s\n", nhead, nsec, dev_name);
|
||||
seenpart = 0;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -695,12 +695,12 @@ void getboot(char *buffer)
|
|||
|
||||
segread(&sregs); /* get ds */
|
||||
|
||||
if (devname[1] != ':') {
|
||||
printf("Invalid drive %s\n", devname);
|
||||
if (dev_name[1] != ':') {
|
||||
printf("Invalid drive %s\n", dev_name);
|
||||
exit(1);
|
||||
}
|
||||
if (*devname >= 'a') *devname += 'A' - 'a';
|
||||
drivenum = (*devname - 'C') & 0xff;
|
||||
if (*dev_name >= 'a') *dev_name += 'A' - 'a';
|
||||
drivenum = (*dev_name - 'C') & 0xff;
|
||||
if (drivenum < 0 || drivenum > 7) {
|
||||
printf("Funny drive number %d\n", drivenum);
|
||||
exit(1);
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
PROG= gcore
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
/* gcore - create core file of running process */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
pid_t pid;
|
||||
int status;
|
||||
|
||||
if(argc != 2) {
|
||||
printf("usage: %s <pid>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pid = atoi(argv[1]);
|
||||
|
||||
if (ptrace(T_ATTACH, pid, 0, 0) != 0) {
|
||||
perror("ptrace(T_ATTACH)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (waitpid(pid, &status, 0) != pid) {
|
||||
perror("waitpid");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (WIFSTOPPED(status) && WSTOPSIG(status) != SIGSTOP) {
|
||||
/* whatever happens here is fine */
|
||||
ptrace(T_RESUME, pid, 0, WSTOPSIG(status));
|
||||
|
||||
if (waitpid(pid, &status, 0) != pid) {
|
||||
perror("waitpid");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WIFSTOPPED(status)) {
|
||||
fprintf(stderr, "process died while attaching\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ptrace(T_DUMPCORE, pid, 0, 0)) {
|
||||
fprintf(stderr, "warning, dumpcore failed (%s)\n", strerror(errno));
|
||||
}
|
||||
|
||||
if (ptrace(T_DETACH, pid, 0, 0)) {
|
||||
fprintf(stderr, "warning, detaching failed (%s)\n", strerror(errno));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -24,11 +24,12 @@ int main(argc, argv)
|
|||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int all = 0, i, v = 0, mountflags;
|
||||
int all = 0, i, v = 0, mountflags, srvflags;
|
||||
char **ap, *opt, *err, *type, *args, *device;
|
||||
|
||||
if (argc == 1) list(); /* just list /etc/mtab */
|
||||
mountflags = 0;
|
||||
srvflags = 0;
|
||||
type = NULL;
|
||||
args = NULL;
|
||||
ap = argv+1;
|
||||
|
|
@ -36,12 +37,12 @@ char *argv[];
|
|||
if (argv[i][0] == '-') {
|
||||
opt = argv[i]+1;
|
||||
while (*opt != 0) switch (*opt++) {
|
||||
case 'r': mountflags |= MS_RDONLY; break;
|
||||
case 'r': mountflags |= MNT_RDONLY; break;
|
||||
case 't': if (++i == argc) usage();
|
||||
type = argv[i];
|
||||
break;
|
||||
case 'i': mountflags |= MS_REUSE; break;
|
||||
case 'e': mountflags |= MS_EXISTING; break;
|
||||
case 'i': srvflags |= MS_REUSE; break;
|
||||
case 'e': srvflags |= MS_EXISTING; break;
|
||||
case 'n': write_mtab = 0; break;
|
||||
case 'o': if (++i == argc) usage();
|
||||
args = argv[i];
|
||||
|
|
@ -75,7 +76,7 @@ char *argv[];
|
|||
}
|
||||
}
|
||||
|
||||
if (mount(device, argv[2], mountflags, type, args) < 0) {
|
||||
if (mount(device, argv[2], mountflags, srvflags, type, args) < 0) {
|
||||
err = strerror(errno);
|
||||
fprintf(stderr, "mount: Can't mount %s on %s: %s\n",
|
||||
argv[1], argv[2], err);
|
||||
|
|
@ -141,7 +142,7 @@ mount_all()
|
|||
if (has_opt(fs->fs_mntops, "ro"))
|
||||
ro = 1;
|
||||
if (ro) {
|
||||
mountflags |= MS_RDONLY;
|
||||
mountflags |= MNT_RDONLY;
|
||||
}
|
||||
|
||||
device = fs->fs_spec;
|
||||
|
|
@ -152,7 +153,7 @@ mount_all()
|
|||
if (!strcmp(device, "none"))
|
||||
device = NULL;
|
||||
|
||||
if (mount(device, mountpoint, mountflags, fs->fs_vfstype,
|
||||
if (mount(device, mountpoint, mountflags, 0, fs->fs_vfstype,
|
||||
fs->fs_mntops) != 0) {
|
||||
err = strerror(errno);
|
||||
fprintf(stderr, "mount: Can't mount %s on %s: %s\n",
|
||||
|
|
|
|||
|
|
@ -66,15 +66,36 @@ void usage()
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
int open_audio(unsigned int *fragment_size, unsigned int channels,
|
||||
unsigned int samples_per_sec, unsigned int bits)
|
||||
{
|
||||
unsigned int sign;
|
||||
int audio;
|
||||
|
||||
/* Open DSP */
|
||||
if ((audio = open("/dev/audio", O_RDWR | O_REOPEN)) < 0)
|
||||
{
|
||||
printf("Cannot open /dev/audio: %s\n", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
ioctl(audio, DSPIOMAX, fragment_size); /* Get maximum fragment size. */
|
||||
|
||||
/* Set DSP parameters (should check return values..) */
|
||||
ioctl(audio, DSPIOSIZE, fragment_size); /* Use max. fragment size. */
|
||||
ioctl(audio, DSPIOSTEREO, &channels);
|
||||
ioctl(audio, DSPIORATE, &samples_per_sec);
|
||||
ioctl(audio, DSPIOBITS, &bits);
|
||||
sign = (bits == 16 ? 1 : 0);
|
||||
ioctl(audio, DSPIOSIGN, &sign);
|
||||
return audio;
|
||||
}
|
||||
|
||||
int main ( int argc, char *argv[] )
|
||||
{
|
||||
int i, r, audio, file;
|
||||
char *buffer, *file_name = NULL;
|
||||
unsigned int sign;
|
||||
unsigned int fragment_size;
|
||||
unsigned int channels;
|
||||
unsigned int bits;
|
||||
unsigned int fragment_size, fragment_size2;
|
||||
long data_pos;
|
||||
int showinfo = 0;
|
||||
|
||||
|
|
@ -91,22 +112,6 @@ int main ( int argc, char *argv[] )
|
|||
}
|
||||
else file_name = argv[1];
|
||||
|
||||
/* Open DSP */
|
||||
if ((audio = open("/dev/audio", O_RDWR | O_REOPEN)) < 0)
|
||||
{
|
||||
printf("Cannot open /dev/audio: %s\n", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Get maximum fragment size and try to allocate a buffer */
|
||||
ioctl(audio, DSPIOMAX, &fragment_size);
|
||||
if ((buffer = malloc(fragment_size)) == (char *)0)
|
||||
{
|
||||
fprintf(stderr, "Cannot allocate buffer\n");
|
||||
exit(-1);
|
||||
}
|
||||
ioctl(audio, DSPIOSIZE, &fragment_size);
|
||||
|
||||
/* Open wav file */
|
||||
if((file = open(file_name, O_RDONLY)) < 0)
|
||||
{
|
||||
|
|
@ -141,15 +146,15 @@ int main ( int argc, char *argv[] )
|
|||
exit(1);
|
||||
}
|
||||
|
||||
/* Set DSP parameters */
|
||||
channels = c_fields.Channels;
|
||||
channels--;
|
||||
bits = s_fields.BitsPerSample;
|
||||
ioctl(audio, DSPIOSTEREO, &channels);
|
||||
ioctl(audio, DSPIORATE, &c_fields.SamplesPerSec);
|
||||
ioctl(audio, DSPIOBITS, &bits);
|
||||
sign = (bits == 16 ? 1 : 0);
|
||||
ioctl(audio, DSPIOSIGN, &sign);
|
||||
/* Open audio device and set DSP parameters */
|
||||
audio = open_audio(&fragment_size, c_fields.Channels - 1,
|
||||
c_fields.SamplesPerSec, s_fields.BitsPerSample);
|
||||
|
||||
if ((buffer = malloc(fragment_size)) == (char *)0)
|
||||
{
|
||||
fprintf(stderr, "Cannot allocate buffer\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Goto data chunk */
|
||||
lseek(file, data_pos, SEEK_SET);
|
||||
|
|
@ -203,6 +208,20 @@ int main ( int argc, char *argv[] )
|
|||
{
|
||||
fprintf(stderr, "playwave: write to audio device failed: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
/* If we get EIO, the driver might have restarted. Reopen the
|
||||
* audio device.
|
||||
*/
|
||||
if (errno == EIO) {
|
||||
close(audio);
|
||||
audio = open_audio(&fragment_size2,
|
||||
c_fields.Channels - 1, c_fields.SamplesPerSec,
|
||||
s_fields.BitsPerSample);
|
||||
if (fragment_size2 != fragment_size) {
|
||||
fprintf(stderr, "Fragment size has changed\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -203,7 +203,6 @@ static char *prrecv(struct pstat *ps)
|
|||
case FSTATE_LOCK: blkstr = "flock"; break;
|
||||
case FSTATE_POPEN: blkstr = "popen"; break;
|
||||
case FSTATE_SELECT: blkstr = "select"; break;
|
||||
case FSTATE_DOPEN: blkstr = "dopen"; break;
|
||||
case FSTATE_TASK: blkstr = taskname(ps->ps_ftask); break;
|
||||
default: blkstr = "??"; break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -734,6 +734,7 @@ struct
|
|||
{ "PROCCTL", VM_PROCCTL },
|
||||
{ "MAPCACHEPAGE", VM_MAPCACHEPAGE },
|
||||
{ "SETCACHEPAGE", VM_SETCACHEPAGE },
|
||||
{ "CLEARCACHE", VM_CLEARCACHE },
|
||||
{ "VFS_MMAP", VM_VFS_MMAP },
|
||||
{ "VFS_REPLY", VM_VFS_REPLY },
|
||||
{ NULL, 0 },
|
||||
|
|
|
|||
|
|
@ -334,10 +334,10 @@ static int parse_arguments(int argc, char **argv, u32_t *rss_flags)
|
|||
}
|
||||
}
|
||||
else if (strcmp(argv[i], ARG_DEVSTYLE)==0) {
|
||||
char* dev_style_keys[] = { "STYLE_DEV", "STYLE_DEVA", "STYLE_TTY",
|
||||
"STYLE_CTTY", "STYLE_CLONE", "STYLE_CLONE_A", NULL };
|
||||
int dev_style_values[] = { STYLE_DEV, STYLE_DEVA, STYLE_TTY,
|
||||
STYLE_CTTY, STYLE_CLONE, STYLE_CLONE_A };
|
||||
char* dev_style_keys[] = { "STYLE_DEV", "STYLE_TTY",
|
||||
"STYLE_CTTY", NULL };
|
||||
int dev_style_values[] = { STYLE_DEV, STYLE_TTY,
|
||||
STYLE_CTTY };
|
||||
for(j=0;dev_style_keys[j]!=NULL;j++) {
|
||||
if(!strcmp(dev_style_keys[j], argv[i+1])) {
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -432,9 +432,9 @@ then
|
|||
|
||||
# Get sizes and space availability while the file systems are still
|
||||
# mounted. Otherwise we have to mount them again just for this.
|
||||
required_root_space=`df -k /dev/$root | awk '{print $4}' | tail -n 1`
|
||||
free_root_space=`df -k /dev/$root | awk '{print $3}' | tail -n 1`
|
||||
free_usr_space=`df -k /dev/$usr | awk '{print $3}' | tail -n 1`
|
||||
required_root_space=`df -kP /dev/$root | awk '{print $3}' | tail -n 1`
|
||||
free_root_space=`df -kP /dev/$root | awk '{print $4}' | tail -n 1`
|
||||
free_usr_space=`df -kP /dev/$usr | awk '{print $4}' | tail -n 1`
|
||||
|
||||
umount /mnt/usr && umount /mnt || exit
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ char *argv[];
|
|||
|
||||
found = find_mtab_entry(name);
|
||||
|
||||
if (umount2(name, umount_flags) < 0) {
|
||||
if (umount(name, umount_flags) < 0) {
|
||||
if (errno == EINVAL)
|
||||
std_err("umount: Device not mounted\n");
|
||||
else if (errno == ENOTBLK)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,16 @@
|
|||
./boot/minix/.temp/mod07_log minix-sys
|
||||
./boot/minix/.temp/mod08_tty minix-sys
|
||||
./boot/minix/.temp/mod09_mfs minix-sys
|
||||
./boot/minix/.temp/mod10_vm minix-sys
|
||||
./boot/minix/.temp/mod11_pfs minix-sys
|
||||
./boot/minix/.temp/mod12_init minix-sys
|
||||
./boot/minix/.temp/mod07_tty minix-sys
|
||||
./boot/minix/.temp/mod08_mfs minix-sys
|
||||
./boot/minix/.temp/mod09_vm minix-sys
|
||||
./boot/minix/.temp/mod10_pfs minix-sys
|
||||
./boot/minix/.temp/mod11_init minix-sys
|
||||
./etc/rc.capes minix-sys
|
||||
./etc/rc.capes/BB-BONE-WTHR-01 minix-sys
|
||||
./etc/system.conf.d/lan8710a minix-sys
|
||||
./multiboot/mod07_log minix-sys
|
||||
./multiboot/mod08_tty minix-sys
|
||||
./multiboot/mod09_mfs minix-sys
|
||||
./multiboot/mod10_vm minix-sys
|
||||
./multiboot/mod11_pfs minix-sys
|
||||
./multiboot/mod12_init minix-sys
|
||||
./multiboot/mod07_tty minix-sys
|
||||
./multiboot/mod08_mfs minix-sys
|
||||
./multiboot/mod09_vm minix-sys
|
||||
./multiboot/mod10_pfs minix-sys
|
||||
./multiboot/mod11_init minix-sys
|
||||
./sbin/gpio minix-sys
|
||||
./usr/bin/eepromread minix-sys
|
||||
./usr/include/arm minix-sys
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
|
||||
./boot/minix/.temp/mod07_log minix-sys
|
||||
./boot/minix/.temp/mod08_tty minix-sys
|
||||
./boot/minix/.temp/mod09_mfs minix-sys
|
||||
./boot/minix/.temp/mod10_vm minix-sys
|
||||
./boot/minix/.temp/mod11_pfs minix-sys
|
||||
./boot/minix/.temp/mod12_init minix-sys
|
||||
./boot/minix/.temp/mod07_tty minix-sys
|
||||
./boot/minix/.temp/mod08_mfs minix-sys
|
||||
./boot/minix/.temp/mod09_vm minix-sys
|
||||
./boot/minix/.temp/mod10_pfs minix-sys
|
||||
./boot/minix/.temp/mod11_init minix-sys
|
||||
./etc/system.conf.d/atl2 minix-sys
|
||||
./etc/system.conf.d/dec21140A minix-sys
|
||||
./etc/system.conf.d/e1000 minix-sys
|
||||
|
|
@ -13,12 +12,11 @@
|
|||
./etc/system.conf.d/rtl8139 minix-sys
|
||||
./etc/system.conf.d/rtl8169 minix-sys
|
||||
./etc/system.conf.d/virtio_net minix-sys
|
||||
./multiboot/mod07_log minix-sys
|
||||
./multiboot/mod08_tty minix-sys
|
||||
./multiboot/mod09_mfs minix-sys
|
||||
./multiboot/mod10_vm minix-sys
|
||||
./multiboot/mod11_pfs minix-sys
|
||||
./multiboot/mod12_init minix-sys
|
||||
./multiboot/mod07_tty minix-sys
|
||||
./multiboot/mod08_mfs minix-sys
|
||||
./multiboot/mod09_vm minix-sys
|
||||
./multiboot/mod10_pfs minix-sys
|
||||
./multiboot/mod11_init minix-sys
|
||||
./sbin/ahci minix-sys
|
||||
./sbin/at_wini minix-sys
|
||||
./sbin/floppy minix-sys
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
./bin/cpio minix-sys
|
||||
./bin/date minix-sys
|
||||
./bin/dev2name minix-sys obsolete
|
||||
./bin/df minix-sys
|
||||
./bin/echo minix-sys
|
||||
./bin/ed minix-sys
|
||||
./bin/expr minix-sys
|
||||
|
|
@ -278,14 +279,14 @@
|
|||
./usr/bin/DESCRIBE minix-sys
|
||||
./usr/bin/devmand minix-sys
|
||||
./usr/bin/devsize minix-sys
|
||||
./usr/bin/df minix-sys
|
||||
./usr/bin/df minix-sys obsolete
|
||||
./usr/bin/dhcpd minix-sys
|
||||
./usr/bin/dhrystone minix-sys
|
||||
./usr/bin/diff minix-sys
|
||||
./usr/bin/dirname minix-sys
|
||||
./usr/bin/diskctl minix-sys
|
||||
./usr/bin/du minix-sys
|
||||
./usr/bin/dumpcore minix-sys
|
||||
./usr/bin/dumpcore minix-sys obsolete
|
||||
./usr/bin/egrep minix-sys
|
||||
./usr/bin/eject minix-sys
|
||||
./usr/bin/elfedit minix-sys binutils
|
||||
|
|
@ -314,7 +315,7 @@
|
|||
./usr/bin/ftp minix-sys
|
||||
./usr/bin/g++ minix-sys gcccmds
|
||||
./usr/bin/gcc minix-sys gcccmds
|
||||
./usr/bin/gcore minix-sys
|
||||
./usr/bin/gcore minix-sys obsolete
|
||||
./usr/bin/gcov minix-sys gcccmds
|
||||
./usr/bin/gcov-pull minix-sys
|
||||
./usr/bin/gcpp minix-sys gcccmds
|
||||
|
|
@ -617,6 +618,7 @@
|
|||
./usr/include/dev minix-sys
|
||||
./usr/include/dev/i2c minix-sys
|
||||
./usr/include/dev/i2c/i2c_io.h minix-sys
|
||||
./usr/include/dev/vndvar.h minix-sys
|
||||
./usr/include/dirent.h minix-sys
|
||||
./usr/include/disktab.h minix-sys
|
||||
./usr/include/dlfcn.h minix-sys
|
||||
|
|
@ -1166,7 +1168,7 @@
|
|||
./usr/include/minix/sysutil.h minix-sys
|
||||
./usr/include/minix/termios.h minix-sys
|
||||
./usr/include/minix/timers.h minix-sys
|
||||
./usr/include/minix/tty.h minix-sys
|
||||
./usr/include/minix/tty.h minix-sys obsolete
|
||||
./usr/include/minix/type.h minix-sys
|
||||
./usr/include/minix/types.h minix-sys obsolete
|
||||
./usr/include/minix/u64.h minix-sys
|
||||
|
|
@ -1828,7 +1830,7 @@
|
|||
./usr/man/man1/dosread.1 minix-sys
|
||||
./usr/man/man1/doswrite.1 minix-sys
|
||||
./usr/man/man1/du.1 minix-sys
|
||||
./usr/man/man1/dumpcore.1 minix-sys
|
||||
./usr/man/man1/dumpcore.1 minix-sys obsolete
|
||||
./usr/man/man1/echo.1 minix-sys
|
||||
./usr/man/man1/ed.1 minix-sys
|
||||
./usr/man/man1/egrep.1 minix-sys
|
||||
|
|
@ -2114,6 +2116,7 @@
|
|||
./usr/man/man2/FD_SET.2 minix-sys
|
||||
./usr/man/man2/fork.2 minix-sys
|
||||
./usr/man/man2/fstatvfs.2 minix-sys
|
||||
./usr/man/man2/fstatvfs1.2 minix-sys
|
||||
./usr/man/man2/getgid.2 minix-sys
|
||||
./usr/man/man2/getitimer.2 minix-sys
|
||||
./usr/man/man2/getnucred.2 minix-sys
|
||||
|
|
@ -2126,6 +2129,7 @@
|
|||
./usr/man/man2/getsockopt.2 minix-sys
|
||||
./usr/man/man2/gettimeofday.2 minix-sys
|
||||
./usr/man/man2/getuid.2 minix-sys
|
||||
./usr/man/man2/getvfsstat.2 minix-sys
|
||||
./usr/man/man2/intro.2 minix-sys
|
||||
./usr/man/man2/ioctl.2 minix-sys
|
||||
./usr/man/man2/kill.2 minix-sys
|
||||
|
|
@ -2165,6 +2169,7 @@
|
|||
./usr/man/man2/socket.2 minix-sys
|
||||
./usr/man/man2/socketpair.2 minix-sys
|
||||
./usr/man/man2/statvfs.2 minix-sys
|
||||
./usr/man/man2/statvfs1.2 minix-sys
|
||||
./usr/man/man2/svrctl.2 minix-sys
|
||||
./usr/man/man2/symlink.2 minix-sys
|
||||
./usr/man/man2/sync.2 minix-sys
|
||||
|
|
@ -3961,6 +3966,7 @@
|
|||
./usr/man/man3/strnvis.3 minix-sys
|
||||
./usr/man/man3/strnvisx.3 minix-sys
|
||||
./usr/man/man3/strpbrk.3 minix-sys
|
||||
./usr/man/man3/strpct.3 minix-sys
|
||||
./usr/man/man3/strptime.3 minix-sys
|
||||
./usr/man/man3/strrchr.3 minix-sys
|
||||
./usr/man/man3/strsep.3 minix-sys
|
||||
|
|
@ -4436,6 +4442,8 @@
|
|||
./usr/man/man8/usermod.8 minix-sys
|
||||
./usr/man/man8/vbfs.8 minix-sys
|
||||
./usr/man/man8/vipw.8 minix-sys
|
||||
./usr/man/man8/vnconfig.8 minix-sys
|
||||
./usr/man/man8/vndconfig.8 minix-sys
|
||||
./usr/man/man8/zdump.8 minix-sys
|
||||
./usr/man/man8/zic.8 minix-sys
|
||||
./usr/man/man9 minix-sys
|
||||
|
|
@ -4488,6 +4496,9 @@
|
|||
./usr/sbin/vfs minix-sys
|
||||
./usr/sbin/vipw minix-sys
|
||||
./usr/sbin/vm minix-sys
|
||||
./usr/sbin/vnconfig minix-sys
|
||||
./usr/sbin/vndconfig minix-sys
|
||||
./usr/sbin/vnd minix-sys
|
||||
./usr/sbin/zic minix-sys
|
||||
./usr/share minix-sys
|
||||
./usr/share/atf minix-sys atf
|
||||
|
|
@ -5289,6 +5300,7 @@
|
|||
./usr/tests/minix-posix/t40d minix-sys
|
||||
./usr/tests/minix-posix/t40e minix-sys
|
||||
./usr/tests/minix-posix/t40f minix-sys
|
||||
./usr/tests/minix-posix/t40g minix-sys
|
||||
./usr/tests/minix-posix/t60a minix-sys
|
||||
./usr/tests/minix-posix/t60b minix-sys
|
||||
./usr/tests/minix-posix/t67a minix-sys
|
||||
|
|
@ -5364,6 +5376,8 @@
|
|||
./usr/tests/minix-posix/test73 minix-sys
|
||||
./usr/tests/minix-posix/test74 minix-sys
|
||||
./usr/tests/minix-posix/test75 minix-sys
|
||||
./usr/tests/minix-posix/test76 minix-sys
|
||||
./usr/tests/minix-posix/test77 minix-sys
|
||||
./usr/tests/minix-posix/test8 minix-sys
|
||||
./usr/tests/minix-posix/test9 minix-sys
|
||||
./usr/tests/minix-posix/testinterp minix-sys
|
||||
|
|
@ -5371,6 +5385,14 @@
|
|||
./usr/tests/minix-posix/testsh2 minix-sys
|
||||
./usr/tests/minix-posix/testvm minix-sys
|
||||
./usr/tests/minix-posix/testvm.conf minix-sys
|
||||
./usr/tests/minix-posix/testvnd minix-sys
|
||||
./usr/tests/minix-posix/tvnd minix-sys
|
||||
./usr/tests/minix-posix/blocktest minix-sys
|
||||
./usr/tests/minix-posix/blocktest/README minix-sys
|
||||
./usr/tests/minix-posix/blocktest/blocktest minix-sys
|
||||
./usr/tests/minix-posix/blocktest/support.sh minix-sys
|
||||
./usr/tests/minix-posix/blocktest/system.conf minix-sys
|
||||
./usr/tests/minix-posix/blocktest/test.sh minix-sys
|
||||
./usr/tests/usr.bin/jot/Atffile minix-sys atf
|
||||
./usr/tests/usr.bin/jot/d_basic.out minix-sys atf
|
||||
./usr/tests/usr.bin/jot/t_jot minix-sys atf
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@ SUBDIR= log tty
|
|||
SUBDIR= ahci amddev atl2 at_wini audio dec21140A dp8390 dpeth \
|
||||
e1000 fbd filter floppy fxp hello lance log mmc orinoco pci printer \
|
||||
random readclock rtl8139 rtl8169 ti1225 tty vbox acpi \
|
||||
virtio_blk virtio_net
|
||||
virtio_blk virtio_net vnd
|
||||
.endif
|
||||
|
||||
.if ${MACHINE_ARCH} == "earm"
|
||||
SUBDIR= bmp085 cat24c256 fb gpio i2c mmc lan8710a log readclock \
|
||||
sht21 tda19988 tps65217 tps65950 tsl2550 tty random
|
||||
sht21 tda19988 tps65217 tps65950 tsl2550 tty random vnd
|
||||
.endif
|
||||
|
||||
.endif # ${MKIMAGEONLY} != "yes"
|
||||
|
|
|
|||
|
|
@ -236,32 +236,29 @@ static void port_timeout(struct timer *tp);
|
|||
static void port_disconnect(struct port_state *ps);
|
||||
|
||||
static char *ahci_portname(struct port_state *ps);
|
||||
static int ahci_open(dev_t minor, int access);
|
||||
static int ahci_close(dev_t minor);
|
||||
static ssize_t ahci_transfer(dev_t minor, int do_write, u64_t position,
|
||||
static int ahci_open(devminor_t minor, int access);
|
||||
static int ahci_close(devminor_t minor);
|
||||
static ssize_t ahci_transfer(devminor_t minor, int do_write, u64_t position,
|
||||
endpoint_t endpt, iovec_t *iovec, unsigned int count, int flags);
|
||||
static struct device *ahci_part(dev_t minor);
|
||||
static struct device *ahci_part(devminor_t minor);
|
||||
static void ahci_alarm(clock_t stamp);
|
||||
static int ahci_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||
cp_grant_id_t grant);
|
||||
static int ahci_ioctl(devminor_t minor, unsigned long request,
|
||||
endpoint_t endpt, cp_grant_id_t grant, endpoint_t user_endpt);
|
||||
static void ahci_intr(unsigned int mask);
|
||||
static int ahci_device(dev_t minor, device_id_t *id);
|
||||
static struct port_state *ahci_get_port(dev_t minor);
|
||||
static int ahci_device(devminor_t minor, device_id_t *id);
|
||||
static struct port_state *ahci_get_port(devminor_t minor);
|
||||
|
||||
/* AHCI driver table. */
|
||||
static struct blockdriver ahci_dtab = {
|
||||
BLOCKDRIVER_TYPE_DISK,
|
||||
ahci_open,
|
||||
ahci_close,
|
||||
ahci_transfer,
|
||||
ahci_ioctl,
|
||||
NULL, /* bdr_cleanup */
|
||||
ahci_part,
|
||||
NULL, /* bdr_geometry */
|
||||
ahci_intr,
|
||||
ahci_alarm,
|
||||
NULL, /* bdr_other */
|
||||
ahci_device
|
||||
.bdr_type = BLOCKDRIVER_TYPE_DISK,
|
||||
.bdr_open = ahci_open,
|
||||
.bdr_close = ahci_close,
|
||||
.bdr_transfer = ahci_transfer,
|
||||
.bdr_ioctl = ahci_ioctl,
|
||||
.bdr_part = ahci_part,
|
||||
.bdr_intr = ahci_intr,
|
||||
.bdr_alarm = ahci_alarm,
|
||||
.bdr_device = ahci_device
|
||||
};
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
@ -2421,7 +2418,7 @@ static char *ahci_portname(struct port_state *ps)
|
|||
/*===========================================================================*
|
||||
* ahci_map_minor *
|
||||
*===========================================================================*/
|
||||
static struct port_state *ahci_map_minor(dev_t minor, struct device **dvp)
|
||||
static struct port_state *ahci_map_minor(devminor_t minor, struct device **dvp)
|
||||
{
|
||||
/* Map a minor device number to a port and a pointer to the partition's
|
||||
* device structure. Return NULL if this minor device number does not
|
||||
|
|
@ -2432,7 +2429,7 @@ static struct port_state *ahci_map_minor(dev_t minor, struct device **dvp)
|
|||
|
||||
ps = NULL;
|
||||
|
||||
if (minor < NR_MINORS) {
|
||||
if (minor >= 0 && minor < NR_MINORS) {
|
||||
port = ahci_map[minor / DEV_PER_DRIVE];
|
||||
|
||||
if (port == NO_PORT)
|
||||
|
|
@ -2457,7 +2454,7 @@ static struct port_state *ahci_map_minor(dev_t minor, struct device **dvp)
|
|||
/*===========================================================================*
|
||||
* ahci_part *
|
||||
*===========================================================================*/
|
||||
static struct device *ahci_part(dev_t minor)
|
||||
static struct device *ahci_part(devminor_t minor)
|
||||
{
|
||||
/* Return a pointer to the partition information structure of the given
|
||||
* minor device.
|
||||
|
|
@ -2473,7 +2470,7 @@ static struct device *ahci_part(dev_t minor)
|
|||
/*===========================================================================*
|
||||
* ahci_open *
|
||||
*===========================================================================*/
|
||||
static int ahci_open(dev_t minor, int access)
|
||||
static int ahci_open(devminor_t minor, int access)
|
||||
{
|
||||
/* Open a device.
|
||||
*/
|
||||
|
|
@ -2499,7 +2496,7 @@ static int ahci_open(dev_t minor, int access)
|
|||
return ENXIO;
|
||||
|
||||
/* Some devices may only be opened in read-only mode. */
|
||||
if ((ps->flags & FLAG_READONLY) && (access & W_BIT))
|
||||
if ((ps->flags & FLAG_READONLY) && (access & BDEV_W_BIT))
|
||||
return EACCES;
|
||||
|
||||
if (ps->open_count == 0) {
|
||||
|
|
@ -2542,7 +2539,7 @@ static int ahci_open(dev_t minor, int access)
|
|||
/*===========================================================================*
|
||||
* ahci_close *
|
||||
*===========================================================================*/
|
||||
static int ahci_close(dev_t minor)
|
||||
static int ahci_close(devminor_t minor)
|
||||
{
|
||||
/* Close a device.
|
||||
*/
|
||||
|
|
@ -2598,7 +2595,7 @@ static int ahci_close(dev_t minor)
|
|||
/*===========================================================================*
|
||||
* ahci_transfer *
|
||||
*===========================================================================*/
|
||||
static ssize_t ahci_transfer(dev_t minor, int do_write, u64_t position,
|
||||
static ssize_t ahci_transfer(devminor_t minor, int do_write, u64_t position,
|
||||
endpoint_t endpt, iovec_t *iovec, unsigned int count, int flags)
|
||||
{
|
||||
/* Perform data transfer on the selected device.
|
||||
|
|
@ -2633,8 +2630,8 @@ static ssize_t ahci_transfer(dev_t minor, int do_write, u64_t position,
|
|||
/*===========================================================================*
|
||||
* ahci_ioctl *
|
||||
*===========================================================================*/
|
||||
static int ahci_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||
cp_grant_id_t grant)
|
||||
static int ahci_ioctl(devminor_t minor, unsigned long request,
|
||||
endpoint_t endpt, cp_grant_id_t grant, endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
/* Process I/O control requests.
|
||||
*/
|
||||
|
|
@ -2684,13 +2681,13 @@ static int ahci_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
|||
sizeof(val));
|
||||
}
|
||||
|
||||
return EINVAL;
|
||||
return ENOTTY;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* ahci_device *
|
||||
*===========================================================================*/
|
||||
static int ahci_device(dev_t minor, device_id_t *id)
|
||||
static int ahci_device(devminor_t minor, device_id_t *id)
|
||||
{
|
||||
/* Map a minor device number to a device ID.
|
||||
*/
|
||||
|
|
@ -2708,7 +2705,7 @@ static int ahci_device(dev_t minor, device_id_t *id)
|
|||
/*===========================================================================*
|
||||
* ahci_get_port *
|
||||
*===========================================================================*/
|
||||
static struct port_state *ahci_get_port(dev_t minor)
|
||||
static struct port_state *ahci_get_port(devminor_t minor)
|
||||
{
|
||||
/* Get the port structure associated with the given minor device.
|
||||
* Called only from worker threads, so the minor device is already
|
||||
|
|
|
|||
|
|
@ -264,7 +264,6 @@ typedef struct vumap_phys prd_t;
|
|||
*/
|
||||
#define MAX_DRIVES 8
|
||||
#define NR_MINORS (MAX_DRIVES * DEV_PER_DRIVE)
|
||||
#define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS)
|
||||
#define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE)
|
||||
|
||||
/* Port states. */
|
||||
|
|
|
|||
|
|
@ -140,14 +140,14 @@ static void init_params(void);
|
|||
static void init_drive(struct wini *w, int base_cmd, int base_ctl, int
|
||||
base_dma, int irq, int ack, int hook, int drive);
|
||||
static void init_params_pci(int);
|
||||
static int w_do_open(dev_t minor, int access);
|
||||
static struct device *w_prepare(dev_t dev);
|
||||
static struct device *w_part(dev_t minor);
|
||||
static int w_do_open(devminor_t minor, int access);
|
||||
static struct device *w_prepare(devminor_t dev);
|
||||
static struct device *w_part(devminor_t minor);
|
||||
static int w_identify(void);
|
||||
static char *w_name(void);
|
||||
static int w_specify(void);
|
||||
static int w_io_test(void);
|
||||
static ssize_t w_transfer(dev_t minor, int do_write, u64_t position,
|
||||
static ssize_t w_transfer(devminor_t minor, int do_write, u64_t position,
|
||||
endpoint_t proc_nr, iovec_t *iov, unsigned int nr_req, int flags);
|
||||
static int com_out(struct command *cmd);
|
||||
static int com_out_ext(struct command *cmd);
|
||||
|
|
@ -155,9 +155,9 @@ static int setup_dma(unsigned *sizep, endpoint_t proc_nr, iovec_t *iov,
|
|||
size_t addr_offset, int do_write);
|
||||
static void w_need_reset(void);
|
||||
static void ack_irqs(unsigned int);
|
||||
static int w_do_close(dev_t minor);
|
||||
static int w_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||
cp_grant_id_t grant);
|
||||
static int w_do_close(devminor_t minor);
|
||||
static int w_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
|
||||
cp_grant_id_t grant, endpoint_t user_endpt);
|
||||
static void w_hw_int(unsigned int irqs);
|
||||
static int com_simple(struct command *cmd);
|
||||
static void w_timeout(void);
|
||||
|
|
@ -166,7 +166,7 @@ static void w_intr_wait(void);
|
|||
static int at_intr_wait(void);
|
||||
static int w_waitfor(int mask, int value);
|
||||
static int w_waitfor_dma(int mask, int value);
|
||||
static void w_geometry(dev_t minor, struct part_geom *entry);
|
||||
static void w_geometry(devminor_t minor, struct part_geom *entry);
|
||||
#if ENABLE_ATAPI
|
||||
static int atapi_sendpacket(u8_t *packet, unsigned cnt, int do_dma);
|
||||
static int atapi_intr_wait(int dma, size_t max);
|
||||
|
|
@ -196,18 +196,14 @@ static int at_in(int line, u32_t port, u32_t *value, char *typename,
|
|||
|
||||
/* Entry points to this driver. */
|
||||
static struct blockdriver w_dtab = {
|
||||
BLOCKDRIVER_TYPE_DISK,/* handle partition requests */
|
||||
w_do_open, /* open or mount request, initialize device */
|
||||
w_do_close, /* release device */
|
||||
w_transfer, /* do the I/O */
|
||||
w_ioctl, /* I/O control requests */
|
||||
NULL, /* nothing to clean up */
|
||||
w_part, /* return partition information */
|
||||
w_geometry, /* tell the geometry of the disk */
|
||||
w_hw_int, /* leftover hardware interrupts */
|
||||
NULL, /* ignore leftover alarms */
|
||||
NULL, /* ignore unrecognized messages */
|
||||
NULL /* no multithreading support */
|
||||
.bdr_type = BLOCKDRIVER_TYPE_DISK, /* handle partition requests */
|
||||
.bdr_open = w_do_open, /* open or mount request, initialize device */
|
||||
.bdr_close = w_do_close, /* release device */
|
||||
.bdr_transfer = w_transfer, /* do the I/O */
|
||||
.bdr_ioctl = w_ioctl, /* I/O control requests */
|
||||
.bdr_part = w_part, /* return partition information */
|
||||
.bdr_geometry = w_geometry, /* tell the geometry of the disk */
|
||||
.bdr_intr = w_hw_int, /* leftover hardware interrupts */
|
||||
};
|
||||
|
||||
/* SEF functions and variables. */
|
||||
|
|
@ -583,7 +579,7 @@ static void init_params_pci(int skip)
|
|||
/*===========================================================================*
|
||||
* w_do_open *
|
||||
*===========================================================================*/
|
||||
static int w_do_open(dev_t minor, int access)
|
||||
static int w_do_open(devminor_t minor, int access)
|
||||
{
|
||||
/* Device open: Initialize the controller and read the partition table. */
|
||||
|
||||
|
|
@ -626,7 +622,7 @@ static int w_do_open(dev_t minor, int access)
|
|||
}
|
||||
|
||||
#if ENABLE_ATAPI
|
||||
if ((wn->state & ATAPI) && (access & W_BIT))
|
||||
if ((wn->state & ATAPI) && (access & BDEV_W_BIT))
|
||||
return(EACCES);
|
||||
#endif
|
||||
|
||||
|
|
@ -652,12 +648,12 @@ static int w_do_open(dev_t minor, int access)
|
|||
/*===========================================================================*
|
||||
* w_prepare *
|
||||
*===========================================================================*/
|
||||
static struct device *w_prepare(dev_t device)
|
||||
static struct device *w_prepare(devminor_t device)
|
||||
{
|
||||
/* Prepare for I/O on a device. */
|
||||
w_device = (int) device;
|
||||
|
||||
if (device < NR_MINORS) { /* d0, d0p[0-3], d1, ... */
|
||||
if (device >= 0 && device < NR_MINORS) { /* d0, d0p[0-3], d1, ... */
|
||||
w_drive = device / DEV_PER_DRIVE; /* save drive number */
|
||||
w_wn = &wini[w_drive];
|
||||
w_dv = &w_wn->part[device % DEV_PER_DRIVE];
|
||||
|
|
@ -676,7 +672,7 @@ static struct device *w_prepare(dev_t device)
|
|||
/*===========================================================================*
|
||||
* w_part *
|
||||
*===========================================================================*/
|
||||
static struct device *w_part(dev_t device)
|
||||
static struct device *w_part(devminor_t device)
|
||||
{
|
||||
/* Return a pointer to the partition information of the given minor device. */
|
||||
|
||||
|
|
@ -1172,7 +1168,7 @@ static int error_dma(const struct wini *wn)
|
|||
* w_transfer *
|
||||
*===========================================================================*/
|
||||
static ssize_t w_transfer(
|
||||
dev_t minor, /* minor device to perform the transfer on */
|
||||
devminor_t minor, /* minor device to perform the transfer on */
|
||||
int do_write, /* read or write? */
|
||||
u64_t position, /* offset on device to read or write */
|
||||
endpoint_t proc_nr, /* process doing the request */
|
||||
|
|
@ -1640,7 +1636,7 @@ static void w_need_reset(void)
|
|||
/*===========================================================================*
|
||||
* w_do_close *
|
||||
*===========================================================================*/
|
||||
static int w_do_close(dev_t minor)
|
||||
static int w_do_close(devminor_t minor)
|
||||
{
|
||||
/* Device close: Release a device. */
|
||||
if (w_prepare(minor) == NULL)
|
||||
|
|
@ -1882,7 +1878,7 @@ int value; /* required status */
|
|||
/*===========================================================================*
|
||||
* w_geometry *
|
||||
*===========================================================================*/
|
||||
static void w_geometry(dev_t minor, struct part_geom *entry)
|
||||
static void w_geometry(devminor_t minor, struct part_geom *entry)
|
||||
{
|
||||
struct wini *wn;
|
||||
|
||||
|
|
@ -2215,8 +2211,8 @@ int do_dma;
|
|||
/*===========================================================================*
|
||||
* w_ioctl *
|
||||
*===========================================================================*/
|
||||
static int w_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||
cp_grant_id_t grant)
|
||||
static int w_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
|
||||
cp_grant_id_t grant, endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
int r, timeout, prev, count;
|
||||
struct command cmd;
|
||||
|
|
@ -2290,7 +2286,7 @@ static int w_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
|||
return (w_wn->w_status & (STATUS_ERR|STATUS_WF)) ? EIO : OK;
|
||||
}
|
||||
|
||||
return EINVAL;
|
||||
return ENOTTY;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
|||
|
|
@ -194,7 +194,6 @@
|
|||
#define MAX_SECS 256 /* controller can transfer this many sectors */
|
||||
#define MAX_ERRORS 4 /* how often to try rd/wt before quitting */
|
||||
#define NR_MINORS (MAX_DRIVES * DEV_PER_DRIVE)
|
||||
#define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS)
|
||||
#define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE)
|
||||
#define DELAY_USECS 1000 /* controller timeout in microseconds */
|
||||
#define DELAY_TICKS 1 /* controller timeout in ticks */
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ int drv_stop(int sub_dev)
|
|||
|
||||
|
||||
/* all IO-ctl's sent to the upper driver are passed to this function */
|
||||
int drv_io_ctl(int request, void * val, int * len, int sub_dev) {
|
||||
int drv_io_ctl(unsigned long request, void * val, int * len, int sub_dev) {
|
||||
|
||||
int status;
|
||||
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ int drv_stop(int sub_dev)
|
|||
|
||||
|
||||
/* all IO-ctl's sent to the upper driver are passed to this function */
|
||||
int drv_io_ctl(int request, void * val, int * len, int sub_dev) {
|
||||
int drv_io_ctl(unsigned long request, void * val, int * len, int sub_dev) {
|
||||
|
||||
int status;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ static int get_set_output(struct inout_ctrl *output, int flag);
|
|||
/*=========================================================================*
|
||||
* mixer_ioctl
|
||||
*=========================================================================*/
|
||||
int mixer_ioctl(int request, void *val, int *UNUSED(len)) {
|
||||
int mixer_ioctl(unsigned long request, void *val, int *UNUSED(len)) {
|
||||
int status;
|
||||
|
||||
switch(request) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#define SB16_MIXER_H
|
||||
|
||||
int mixer_init(void);
|
||||
int mixer_ioctl(int request, void *val, int *len);
|
||||
int mixer_ioctl(unsigned long request, void *val, int *len);
|
||||
|
||||
int mixer_set(int reg, int data);
|
||||
int mixer_get(int reg);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
static void dsp_dma_setup(phys_bytes address, int count, int sub_dev);
|
||||
|
||||
static int dsp_ioctl(int request, void *val, int *len);
|
||||
static int dsp_ioctl(unsigned long request, void *val, int *len);
|
||||
static int dsp_set_size(unsigned int size);
|
||||
static int dsp_set_speed(unsigned int speed);
|
||||
static int dsp_set_stereo(unsigned int stereo);
|
||||
|
|
@ -141,7 +141,7 @@ int drv_start(int channel, int DmaMode) {
|
|||
dsp_set_speed(DspSpeed);
|
||||
|
||||
/* Put the speaker on */
|
||||
if(DmaMode == DEV_WRITE_S) {
|
||||
if(DmaMode == WRITE_DMA) {
|
||||
dsp_command (DSP_CMD_SPKON); /* put speaker on */
|
||||
|
||||
/* Program DSP with dma mode */
|
||||
|
|
@ -232,8 +232,9 @@ int drv_resume(int UNUSED(chan)) {
|
|||
|
||||
|
||||
|
||||
int drv_io_ctl(int request, void *val, int *len, int sub_dev) {
|
||||
Dprint(("dsp_ioctl: got ioctl %d, argument: %d sub_dev: %d\n", request, val, sub_dev));
|
||||
int drv_io_ctl(unsigned long request, void *val, int *len, int sub_dev) {
|
||||
Dprint(("dsp_ioctl: got ioctl %lu, argument: %d sub_dev: %d\n",
|
||||
request, val, sub_dev));
|
||||
|
||||
if(sub_dev == AUDIO) {
|
||||
return dsp_ioctl(request, val, len);
|
||||
|
|
@ -262,7 +263,7 @@ int drv_get_frag_size(u32_t *frag_size, int UNUSED(sub_dev)) {
|
|||
|
||||
|
||||
|
||||
static int dsp_ioctl(int request, void *val, int *len) {
|
||||
static int dsp_ioctl(unsigned long request, void *val, int *len) {
|
||||
int status;
|
||||
|
||||
switch(request) {
|
||||
|
|
@ -293,7 +294,7 @@ static void dsp_dma_setup(phys_bytes address, int count, int DmaMode) {
|
|||
pv_set(pvb[1], DMA8_CLEAR, 0x00); /* Clear flip flop */
|
||||
|
||||
/* set DMA mode */
|
||||
pv_set(pvb[2], DMA8_MODE, (DmaMode == DEV_WRITE_S ? DMA8_AUTO_PLAY : DMA8_AUTO_REC));
|
||||
pv_set(pvb[2], DMA8_MODE, (DmaMode == WRITE_DMA ? DMA8_AUTO_PLAY : DMA8_AUTO_REC));
|
||||
|
||||
pv_set(pvb[3], DMA8_ADDR, (u8_t)(address >> 0)); /* Low_byte of address */
|
||||
pv_set(pvb[4], DMA8_ADDR, (u8_t)(address >> 8)); /* High byte of address */
|
||||
|
|
@ -311,7 +312,7 @@ static void dsp_dma_setup(phys_bytes address, int count, int DmaMode) {
|
|||
pv_set(pvb[1], DMA16_CLEAR, 0x00); /* Clear flip flop */
|
||||
|
||||
/* Set dma mode */
|
||||
pv_set(pvb[2], DMA16_MODE, (DmaMode == DEV_WRITE_S ? DMA16_AUTO_PLAY : DMA16_AUTO_REC));
|
||||
pv_set(pvb[2], DMA16_MODE, (DmaMode == WRITE_DMA ? DMA16_AUTO_PLAY : DMA16_AUTO_REC));
|
||||
|
||||
pv_set(pvb[3], DMA16_ADDR, (address >> 1) & 0xFF); /* Low_byte of address */
|
||||
pv_set(pvb[4], DMA16_ADDR, (address >> 9) & 0xFF); /* High byte of address */
|
||||
|
|
|
|||
|
|
@ -151,11 +151,9 @@ static int read_cal_coef(void);
|
|||
static int measure(int32_t * temperature, int32_t * pressure);
|
||||
|
||||
/* libchardriver callbacks */
|
||||
static struct device *bmp085_prepare(dev_t UNUSED(dev));
|
||||
static int bmp085_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t * iov, unsigned nr_req, endpoint_t UNUSED(user_endpt),
|
||||
unsigned int UNUSED(flags));
|
||||
static int bmp085_other(message * m);
|
||||
static ssize_t bmp085_read(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
static void bmp085_other(message * m, int ipc_status);
|
||||
|
||||
/* i2c bus access */
|
||||
static int reg_read(uint8_t reg, uint8_t * val);
|
||||
|
|
@ -171,21 +169,8 @@ static void sef_local_startup(void);
|
|||
|
||||
/* Entry points to this driver from libchardriver. */
|
||||
static struct chardriver bmp085_tab = {
|
||||
.cdr_open = do_nop,
|
||||
.cdr_close = do_nop,
|
||||
.cdr_ioctl = nop_ioctl,
|
||||
.cdr_prepare = bmp085_prepare,
|
||||
.cdr_transfer = bmp085_transfer,
|
||||
.cdr_cleanup = nop_cleanup,
|
||||
.cdr_alarm = nop_alarm,
|
||||
.cdr_cancel = nop_cancel,
|
||||
.cdr_select = nop_select,
|
||||
.cdr_other = bmp085_other
|
||||
};
|
||||
|
||||
static struct device bmp085_device = {
|
||||
.dv_base = 0,
|
||||
.dv_size = 0
|
||||
.cdr_read = bmp085_read,
|
||||
.cdr_other = bmp085_other
|
||||
};
|
||||
|
||||
static int
|
||||
|
|
@ -605,18 +590,12 @@ measure(int32_t * temperature, int32_t * pressure)
|
|||
return OK;
|
||||
}
|
||||
|
||||
static struct device *
|
||||
bmp085_prepare(dev_t UNUSED(dev))
|
||||
static ssize_t
|
||||
bmp085_read(devminor_t UNUSED(minor), u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int UNUSED(flags), cdev_id_t UNUSED(id))
|
||||
{
|
||||
return &bmp085_device;
|
||||
}
|
||||
|
||||
static int
|
||||
bmp085_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t * iov, unsigned nr_req, endpoint_t UNUSED(user_endpt),
|
||||
unsigned int UNUSED(flags))
|
||||
{
|
||||
int bytes, r;
|
||||
u64_t dev_size;
|
||||
int r;
|
||||
uint32_t temperature, pressure;
|
||||
|
||||
r = measure(&temperature, &pressure);
|
||||
|
|
@ -631,48 +610,33 @@ bmp085_transfer(endpoint_t endpt, int opcode, u64_t position,
|
|||
|
||||
log_trace(&log, "%s", buffer);
|
||||
|
||||
bytes = strlen(buffer) - position < iov->iov_size ?
|
||||
strlen(buffer) - position : iov->iov_size;
|
||||
dev_size = (u64_t)strlen(buffer);
|
||||
if (position >= dev_size) return 0;
|
||||
if (position + size > dev_size)
|
||||
size = (size_t)(dev_size - position);
|
||||
|
||||
if (bytes <= 0) {
|
||||
return OK;
|
||||
}
|
||||
r = sys_safecopyto(endpt, grant, 0,
|
||||
(vir_bytes)(buffer + (size_t)position), size);
|
||||
|
||||
switch (opcode) {
|
||||
case DEV_GATHER_S:
|
||||
r = sys_safecopyto(endpt, (cp_grant_id_t) iov->iov_addr, 0,
|
||||
(vir_bytes) (buffer + position), bytes);
|
||||
iov->iov_size -= bytes;
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return r;
|
||||
return (r != OK) ? r : size;
|
||||
}
|
||||
|
||||
static int
|
||||
bmp085_other(message * m)
|
||||
static void
|
||||
bmp085_other(message * m, int ipc_status)
|
||||
{
|
||||
int r;
|
||||
|
||||
switch (m->m_type) {
|
||||
case NOTIFY_MESSAGE:
|
||||
if (is_ipc_notify(ipc_status)) {
|
||||
if (m->m_source == DS_PROC_NR) {
|
||||
log_debug(&log,
|
||||
"bus driver changed state, update endpoint\n");
|
||||
i2cdriver_handle_bus_update(&bus_endpoint, bus,
|
||||
address);
|
||||
}
|
||||
r = OK;
|
||||
break;
|
||||
default:
|
||||
log_warn(&log, "Invalid message type (0x%x)\n", m->m_type);
|
||||
r = EINVAL;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
return r;
|
||||
log_warn(&log, "Invalid message type (0x%x)\n", m->m_type);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -791,7 +755,7 @@ main(int argc, char *argv[])
|
|||
|
||||
sef_local_startup();
|
||||
|
||||
chardriver_task(&bmp085_tab, CHARDRIVER_SYNC);
|
||||
chardriver_task(&bmp085_tab);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,14 +29,14 @@ static int sef_cb_lu_state_save(int);
|
|||
static int lu_state_restore(void);
|
||||
|
||||
/* libblockdriver callbacks */
|
||||
static int cat24c256_blk_open(dev_t minor, int access);
|
||||
static int cat24c256_blk_close(dev_t minor);
|
||||
static ssize_t cat24c256_blk_transfer(dev_t minor, int do_write, u64_t pos,
|
||||
endpoint_t endpt, iovec_t * iov, unsigned count, int flags);
|
||||
static int cat24c256_blk_ioctl(dev_t minor, unsigned int request,
|
||||
endpoint_t endpt, cp_grant_id_t grant);
|
||||
static struct device *cat24c256_blk_part(dev_t minor);
|
||||
static int cat24c256_blk_other(message * m);
|
||||
static int cat24c256_blk_open(devminor_t minor, int access);
|
||||
static int cat24c256_blk_close(devminor_t minor);
|
||||
static ssize_t cat24c256_blk_transfer(devminor_t minor, int do_write,
|
||||
u64_t pos, endpoint_t endpt, iovec_t * iov, unsigned int count, int flags);
|
||||
static int cat24c256_blk_ioctl(devminor_t minor, unsigned long request,
|
||||
endpoint_t endpt, cp_grant_id_t grant, endpoint_t user_endpt);
|
||||
static struct device *cat24c256_blk_part(devminor_t minor);
|
||||
static void cat24c256_blk_other(message * m, int ipc_status);
|
||||
|
||||
/* Entry points into the device dependent code of block drivers. */
|
||||
struct blockdriver cat24c256_tab = {
|
||||
|
|
@ -44,14 +44,9 @@ struct blockdriver cat24c256_tab = {
|
|||
.bdr_open = cat24c256_blk_open,
|
||||
.bdr_close = cat24c256_blk_close,
|
||||
.bdr_transfer = cat24c256_blk_transfer,
|
||||
.bdr_ioctl = cat24c256_blk_ioctl, /* nop -- always returns EINVAL */
|
||||
.bdr_cleanup = NULL, /* nothing allocated -- nothing to clean up */
|
||||
.bdr_ioctl = cat24c256_blk_ioctl, /* always returns ENOTTY */
|
||||
.bdr_part = cat24c256_blk_part,
|
||||
.bdr_geometry = NULL, /* no geometry (cylinders, heads, sectors, etc) */
|
||||
.bdr_intr = NULL, /* i2c devices don't generate interrupts */
|
||||
.bdr_alarm = NULL, /* alarm not needed */
|
||||
.bdr_other = cat24c256_blk_other, /* to recv notify events from DS */
|
||||
.bdr_device = NULL /* 1 insance per bus, threads not needed */
|
||||
.bdr_other = cat24c256_blk_other /* for notify events from DS */
|
||||
};
|
||||
|
||||
static int cat24c256_read128(uint16_t memaddr, void *buf, size_t buflen, int flags);
|
||||
|
|
@ -84,7 +79,7 @@ static struct log log = {
|
|||
};
|
||||
|
||||
static int
|
||||
cat24c256_blk_open(dev_t minor, int access)
|
||||
cat24c256_blk_open(devminor_t minor, int access)
|
||||
{
|
||||
log_trace(&log, "cat24c256_blk_open(%d,%d)\n", minor, access);
|
||||
if (cat24c256_blk_part(minor) == NULL) {
|
||||
|
|
@ -97,7 +92,7 @@ cat24c256_blk_open(dev_t minor, int access)
|
|||
}
|
||||
|
||||
static int
|
||||
cat24c256_blk_close(dev_t minor)
|
||||
cat24c256_blk_close(devminor_t minor)
|
||||
{
|
||||
log_trace(&log, "cat24c256_blk_close(%d)\n", minor);
|
||||
if (cat24c256_blk_part(minor) == NULL) {
|
||||
|
|
@ -114,11 +109,11 @@ cat24c256_blk_close(dev_t minor)
|
|||
}
|
||||
|
||||
static ssize_t
|
||||
cat24c256_blk_transfer(dev_t minor, int do_write, u64_t pos64,
|
||||
endpoint_t endpt, iovec_t * iov, unsigned nr_req, int flags)
|
||||
cat24c256_blk_transfer(devminor_t minor, int do_write, u64_t pos64,
|
||||
endpoint_t endpt, iovec_t * iov, unsigned int nr_req, int flags)
|
||||
{
|
||||
/* Read or write one the driver's block devices. */
|
||||
unsigned count;
|
||||
unsigned int count;
|
||||
struct device *dv;
|
||||
u64_t dv_size;
|
||||
int r;
|
||||
|
|
@ -214,50 +209,40 @@ cat24c256_blk_transfer(dev_t minor, int do_write, u64_t pos64,
|
|||
}
|
||||
|
||||
static int
|
||||
cat24c256_blk_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||
cp_grant_id_t grant)
|
||||
cat24c256_blk_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
|
||||
cp_grant_id_t grant, endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
log_trace(&log, "cat24c256_blk_ioctl(%d)\n", minor);
|
||||
/* no supported ioctls for this device */
|
||||
return EINVAL;
|
||||
return ENOTTY;
|
||||
}
|
||||
|
||||
static struct device *
|
||||
cat24c256_blk_part(dev_t minor)
|
||||
cat24c256_blk_part(devminor_t minor)
|
||||
{
|
||||
log_trace(&log, "cat24c256_blk_part(%d)\n", minor);
|
||||
|
||||
if (minor >= NR_DEVS) {
|
||||
if (minor < 0 || minor >= NR_DEVS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &geom[minor];
|
||||
}
|
||||
|
||||
static int
|
||||
cat24c256_blk_other(message * m)
|
||||
static void
|
||||
cat24c256_blk_other(message * m, int ipc_status)
|
||||
{
|
||||
int r;
|
||||
|
||||
log_trace(&log, "cat24c256_blk_other(0x%x)\n", m->m_type);
|
||||
|
||||
switch (m->m_type) {
|
||||
case NOTIFY_MESSAGE:
|
||||
if (is_ipc_notify(ipc_status)) {
|
||||
if (m->m_source == DS_PROC_NR) {
|
||||
log_debug(&log,
|
||||
"bus driver changed state, update endpoint\n");
|
||||
i2cdriver_handle_bus_update(&bus_endpoint, bus,
|
||||
address);
|
||||
}
|
||||
r = OK;
|
||||
break;
|
||||
default:
|
||||
} else
|
||||
log_warn(&log, "Invalid message type (0x%x)\n", m->m_type);
|
||||
r = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* The lower level i2c interface can only read/write 128 bytes at a time.
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ arch_pan_display(int minor, struct fb_var_screeninfo *fbvsp)
|
|||
}
|
||||
|
||||
int
|
||||
arch_fb_init(int minor, struct device *dev, struct edid_info *info)
|
||||
arch_fb_init(int minor, struct edid_info *info)
|
||||
{
|
||||
int r;
|
||||
u32_t rdispc;
|
||||
|
|
@ -320,13 +320,9 @@ arch_fb_init(int minor, struct device *dev, struct edid_info *info)
|
|||
|
||||
const struct panel_config *panel_cfg = &omap_cfg[minor];
|
||||
|
||||
assert(dev != NULL);
|
||||
if (minor != 0) return ENXIO; /* We support only one minor */
|
||||
|
||||
|
||||
if (initialized) {
|
||||
dev->dv_base = fb_vir;
|
||||
dev->dv_size = fb_size;
|
||||
return OK;
|
||||
} else if (info != NULL) {
|
||||
log_debug(&log, "Configuring Settings based on EDID...\n");
|
||||
|
|
@ -403,8 +399,6 @@ arch_fb_init(int minor, struct device *dev, struct edid_info *info)
|
|||
if (fb_vir == (vir_bytes) MAP_FAILED) {
|
||||
panic("Unable to allocate contiguous memory\n");
|
||||
}
|
||||
dev->dv_base = fb_vir;
|
||||
dev->dv_size = fb_size;
|
||||
|
||||
/* Configure buffer settings and turn on LCD/Digital */
|
||||
arch_configure_display(minor);
|
||||
|
|
|
|||
183
drivers/fb/fb.c
183
drivers/fb/fb.c
|
|
@ -23,17 +23,14 @@
|
|||
/*
|
||||
* Function prototypes for the fb driver.
|
||||
*/
|
||||
static int fb_open(message *m);
|
||||
static int fb_close(message *m);
|
||||
static struct device * fb_prepare(dev_t device);
|
||||
static int fb_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t *iov, unsigned int nr_req, endpoint_t user_endpt, unsigned int
|
||||
flags);
|
||||
static int fb_do_read(endpoint_t ep, iovec_t *iov, int minor, u64_t pos,
|
||||
size_t *io_bytes);
|
||||
static int fb_do_write(endpoint_t ep, iovec_t *iov, int minor, u64_t pos,
|
||||
size_t *io_bytes);
|
||||
static int fb_ioctl(message *m);
|
||||
static int fb_open(devminor_t minor, int access, endpoint_t user_endpt);
|
||||
static int fb_close(devminor_t minor);
|
||||
static ssize_t fb_read(devminor_t minor, u64_t pos, endpoint_t ep,
|
||||
cp_grant_id_t gid, size_t size, int flags, cdev_id_t id);
|
||||
static ssize_t fb_write(devminor_t minor, u64_t pos, endpoint_t ep,
|
||||
cp_grant_id_t gid, size_t size, int flags, cdev_id_t id);
|
||||
static int fb_ioctl(devminor_t minor, unsigned long request, endpoint_t ep,
|
||||
cp_grant_id_t gid, int flags, endpoint_t user_ep, cdev_id_t id);
|
||||
static void paint_bootlogo(int minor);
|
||||
static void paint_restartlogo(int minor);
|
||||
static void paint_centered(int minor, char *data, int width, int height);
|
||||
|
|
@ -52,143 +49,90 @@ static int lu_state_restore(void);
|
|||
/* Entry points to the fb driver. */
|
||||
static struct chardriver fb_tab =
|
||||
{
|
||||
fb_open,
|
||||
fb_close,
|
||||
fb_ioctl,
|
||||
fb_prepare,
|
||||
fb_transfer,
|
||||
nop_cleanup,
|
||||
nop_alarm,
|
||||
nop_cancel,
|
||||
nop_select,
|
||||
NULL
|
||||
.cdr_open = fb_open,
|
||||
.cdr_close = fb_close,
|
||||
.cdr_read = fb_read,
|
||||
.cdr_write = fb_write,
|
||||
.cdr_ioctl = fb_ioctl
|
||||
};
|
||||
|
||||
/** Represents the /dev/fb device. */
|
||||
static struct device fb_device[FB_DEV_NR];
|
||||
static int fb_minor, has_restarted = 0;
|
||||
static int has_restarted = 0;
|
||||
static u64_t has_restarted_t1, has_restarted_t2;
|
||||
|
||||
static int open_counter[FB_DEV_NR]; /* Open count */
|
||||
|
||||
static int
|
||||
fb_open(message *m)
|
||||
fb_open(devminor_t minor, int UNUSED(access), endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
int r;
|
||||
static int initialized = 0;
|
||||
static struct edid_info info;
|
||||
static struct edid_info *infop = NULL;
|
||||
|
||||
if (m->DEVICE < 0 || m->DEVICE >= FB_DEV_NR) return ENXIO;
|
||||
if (minor < 0 || minor >= FB_DEV_NR) return ENXIO;
|
||||
|
||||
if (!initialized) {
|
||||
r = fb_edid_read(m->DEVICE, &info);
|
||||
r = fb_edid_read(minor, &info);
|
||||
infop = (r == 0) ? &info : NULL;
|
||||
}
|
||||
|
||||
if (arch_fb_init(m->DEVICE, &fb_device[m->DEVICE], infop) == OK) {
|
||||
open_counter[m->DEVICE]++;
|
||||
if (arch_fb_init(minor, infop) == OK) {
|
||||
open_counter[minor]++;
|
||||
if (!initialized) {
|
||||
if (has_restarted) {
|
||||
read_frclock_64(&has_restarted_t1);
|
||||
paint_restartlogo(m->DEVICE);
|
||||
paint_restartlogo(minor);
|
||||
} else {
|
||||
paint_bootlogo(m->DEVICE);
|
||||
paint_bootlogo(minor);
|
||||
}
|
||||
initialized = 1;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
return ENXIO ;
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
static int
|
||||
fb_close(message *m)
|
||||
fb_close(devminor_t minor)
|
||||
{
|
||||
if (m->DEVICE < 0 || m->DEVICE >= FB_DEV_NR) return ENXIO;
|
||||
assert(open_counter[m->DEVICE] > 0);
|
||||
open_counter[m->DEVICE]--;
|
||||
if (minor < 0 || minor >= FB_DEV_NR) return ENXIO;
|
||||
assert(open_counter[minor] > 0);
|
||||
open_counter[minor]--;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static struct device *
|
||||
fb_prepare(dev_t dev)
|
||||
{
|
||||
if (dev < 0 || dev >= FB_DEV_NR) return NULL;
|
||||
assert(open_counter[dev] > 0);
|
||||
fb_minor = dev;
|
||||
return &fb_device[dev];
|
||||
}
|
||||
|
||||
static int
|
||||
fb_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t *iov, unsigned nr_req, endpoint_t UNUSED(user_endpt),
|
||||
unsigned int UNUSED(flags))
|
||||
{
|
||||
size_t io_bytes = 0, ret;
|
||||
|
||||
if (nr_req != 1) {
|
||||
/* This should never trigger for char drivers at the moment. */
|
||||
printf("fb: vectored transfer, using first element only\n");
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
case DEV_GATHER_S:
|
||||
/* Userland read operation */
|
||||
ret = fb_do_read(endpt, iov, fb_minor, position, &io_bytes);
|
||||
iov->iov_size -= io_bytes;
|
||||
break;
|
||||
case DEV_SCATTER_S:
|
||||
/* Userland write operation */
|
||||
ret = fb_do_write(endpt, iov, fb_minor, position, &io_bytes);
|
||||
iov->iov_size -= io_bytes;
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
fb_do_read(endpoint_t ep, iovec_t *iov, int minor, u64_t pos, size_t *io_bytes)
|
||||
static ssize_t
|
||||
fb_read(devminor_t minor, u64_t pos, endpoint_t ep, cp_grant_id_t gid,
|
||||
size_t size, int UNUSED(flags), cdev_id_t UNUSED(id))
|
||||
{
|
||||
struct device dev;
|
||||
int r;
|
||||
|
||||
if (minor < 0 || minor >= FB_DEV_NR) return ENXIO;
|
||||
assert(open_counter[minor] > 0);
|
||||
|
||||
arch_get_device(minor, &dev);
|
||||
|
||||
if (pos >= dev.dv_size) return EINVAL;
|
||||
if (size == 0 || pos >= dev.dv_size) return 0;
|
||||
if (pos + size > dev.dv_size)
|
||||
size = (size_t)(dev.dv_size - pos);
|
||||
|
||||
if (dev.dv_size - pos < iov->iov_size) {
|
||||
*io_bytes = dev.dv_size - pos;
|
||||
} else {
|
||||
*io_bytes = iov->iov_size;
|
||||
}
|
||||
r = sys_safecopyto(ep, gid, 0, (vir_bytes)(dev.dv_base + (size_t)pos),
|
||||
size);
|
||||
|
||||
if (*io_bytes <= 0) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
return sys_safecopyto(ep, (cp_grant_id_t) iov->iov_addr, 0,
|
||||
(vir_bytes) (dev.dv_base + ex64lo(pos)),
|
||||
*io_bytes);
|
||||
return (r != OK) ? r : size;
|
||||
}
|
||||
|
||||
static int
|
||||
fb_ioctl(message *m)
|
||||
fb_ioctl(devminor_t minor, unsigned long request, endpoint_t ep,
|
||||
cp_grant_id_t gid, int UNUSED(flags), endpoint_t UNUSED(user_ep),
|
||||
cdev_id_t UNUSED(id))
|
||||
{
|
||||
/* Process I/O control requests */
|
||||
endpoint_t ep;
|
||||
cp_grant_id_t gid;
|
||||
int minor;
|
||||
unsigned int request;
|
||||
int r;
|
||||
|
||||
minor = m->DEVICE;
|
||||
request = m->COUNT;
|
||||
ep = (endpoint_t) m->USER_ENDPT;
|
||||
gid = (cp_grant_id_t) m->IO_GRANT;
|
||||
|
||||
if (minor != 0) return EINVAL;
|
||||
if (minor < 0 || minor >= FB_DEV_NR) return ENXIO;
|
||||
|
||||
switch(request) {
|
||||
case FBIOGET_VSCREENINFO:
|
||||
|
|
@ -205,7 +149,7 @@ fb_ioctl(message *m)
|
|||
return r;
|
||||
}
|
||||
|
||||
return EINVAL;
|
||||
return ENOTTY;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -270,34 +214,29 @@ do_get_fixscreeninfo(int minor, endpoint_t ep, cp_grant_id_t gid)
|
|||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
fb_do_write(endpoint_t ep, iovec_t *iov, int minor, u64_t pos, size_t *io_bytes)
|
||||
static ssize_t
|
||||
fb_write(devminor_t minor, u64_t pos, endpoint_t ep, cp_grant_id_t gid,
|
||||
size_t size, int UNUSED(flags), cdev_id_t UNUSED(id))
|
||||
{
|
||||
struct device dev;
|
||||
int r;
|
||||
|
||||
if (minor < 0 || minor >= FB_DEV_NR) return ENXIO;
|
||||
assert(open_counter[minor] > 0);
|
||||
|
||||
if (has_restarted && keep_displaying_restarted())
|
||||
return EAGAIN;
|
||||
|
||||
arch_get_device(minor, &dev);
|
||||
|
||||
if (pos >= dev.dv_size) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (size == 0 || pos >= dev.dv_size) return 0;
|
||||
if (pos + size > dev.dv_size)
|
||||
size = (size_t)(dev.dv_size - pos);
|
||||
|
||||
if (dev.dv_size - pos < iov->iov_size) {
|
||||
*io_bytes = dev.dv_size - pos;
|
||||
} else {
|
||||
*io_bytes = iov->iov_size;
|
||||
}
|
||||
r = sys_safecopyfrom(ep, gid, 0,
|
||||
(vir_bytes)(dev.dv_base + (size_t)pos), size);
|
||||
|
||||
if (*io_bytes <= 0) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (has_restarted && keep_displaying_restarted()) {
|
||||
return EAGAIN;
|
||||
}
|
||||
|
||||
return sys_safecopyfrom(ep, (cp_grant_id_t) iov->iov_addr, 0,
|
||||
(vir_bytes) (dev.dv_base + ex64lo(pos)),
|
||||
*io_bytes);
|
||||
return (r != OK) ? r : size;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -382,7 +321,7 @@ main(int argc, char *argv[])
|
|||
fb_edid_args_parse();
|
||||
|
||||
sef_local_startup();
|
||||
chardriver_task(&fb_tab, CHARDRIVER_SYNC);
|
||||
chardriver_task(&fb_tab);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <minix/fb.h>
|
||||
|
||||
int arch_fb_init(int minor, struct device *dev, struct edid_info *info);
|
||||
int arch_fb_init(int minor, struct edid_info *info);
|
||||
int arch_get_device(int minor, struct device *dev);
|
||||
int arch_get_varscreeninfo(int minor, struct fb_var_screeninfo *fbvsp);
|
||||
int arch_put_varscreeninfo(int minor, struct fb_var_screeninfo *fbvs_copy);
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ do_read(endpoint_t driver_endpt, uint8_t *buf, size_t bufsize)
|
|||
/* Open Device - required for drivers using libblockdriver */
|
||||
memset(&m, '\0', sizeof(message));
|
||||
m.m_type = BDEV_OPEN;
|
||||
m.BDEV_ACCESS = R_BIT;
|
||||
m.BDEV_ACCESS = BDEV_R_BIT;
|
||||
m.BDEV_ID = 0;
|
||||
m.BDEV_MINOR = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,34 +15,27 @@
|
|||
#define BUF_SIZE (NR_IOREQS * CLICK_SIZE) /* 256k */
|
||||
|
||||
/* Function declarations. */
|
||||
static int fbd_open(dev_t minor, int access);
|
||||
static int fbd_close(dev_t minor);
|
||||
static int fbd_transfer(dev_t minor, int do_write, u64_t position,
|
||||
static int fbd_open(devminor_t minor, int access);
|
||||
static int fbd_close(devminor_t minor);
|
||||
static int fbd_transfer(devminor_t minor, int do_write, u64_t position,
|
||||
endpoint_t endpt, iovec_t *iov, unsigned int nr_req, int flags);
|
||||
static int fbd_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||
cp_grant_id_t grant);
|
||||
static int fbd_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
|
||||
cp_grant_id_t grant, endpoint_t user_endpt);
|
||||
|
||||
/* Variables. */
|
||||
static char *fbd_buf; /* scratch buffer */
|
||||
|
||||
static char driver_label[32] = ""; /* driver DS label */
|
||||
static dev_t driver_minor = -1; /* driver's partition minor to use */
|
||||
static endpoint_t driver_endpt; /* driver endpoint */
|
||||
static devminor_t driver_minor = -1; /* driver's partition minor to use */
|
||||
static endpoint_t driver_endpt; /* driver endpoint */
|
||||
|
||||
/* Entry points to this driver. */
|
||||
static struct blockdriver fbd_dtab = {
|
||||
BLOCKDRIVER_TYPE_OTHER, /* do not handle partition requests */
|
||||
fbd_open, /* open or mount request, initialize device */
|
||||
fbd_close, /* release device */
|
||||
fbd_transfer, /* do the I/O */
|
||||
fbd_ioctl, /* perform I/O control request */
|
||||
NULL, /* nothing to clean up */
|
||||
NULL, /* we will not be asked about partitions */
|
||||
NULL, /* we will not be asked for geometry */
|
||||
NULL, /* ignore leftover hardware interrupts */
|
||||
NULL, /* ignore alarms */
|
||||
NULL, /* ignore other messages */
|
||||
NULL /* no multithreading support */
|
||||
.bdr_type = BLOCKDRIVER_TYPE_OTHER,/* do not handle part. reqs */
|
||||
.bdr_open = fbd_open, /* open request, initialize device */
|
||||
.bdr_close = fbd_close, /* release device */
|
||||
.bdr_transfer = fbd_transfer, /* do the I/O */
|
||||
.bdr_ioctl = fbd_ioctl /* perform I/O control request */
|
||||
};
|
||||
|
||||
/* Options supported by this driver. */
|
||||
|
|
@ -147,7 +140,7 @@ int main(int argc, char **argv)
|
|||
/*===========================================================================*
|
||||
* fbd_open *
|
||||
*===========================================================================*/
|
||||
static int fbd_open(dev_t UNUSED(minor), int access)
|
||||
static int fbd_open(devminor_t UNUSED(minor), int access)
|
||||
{
|
||||
/* Open a device. */
|
||||
message m;
|
||||
|
|
@ -172,7 +165,7 @@ static int fbd_open(dev_t UNUSED(minor), int access)
|
|||
/*===========================================================================*
|
||||
* fbd_close *
|
||||
*===========================================================================*/
|
||||
static int fbd_close(dev_t UNUSED(minor))
|
||||
static int fbd_close(devminor_t UNUSED(minor))
|
||||
{
|
||||
/* Close a device. */
|
||||
message m;
|
||||
|
|
@ -196,8 +189,8 @@ static int fbd_close(dev_t UNUSED(minor))
|
|||
/*===========================================================================*
|
||||
* fbd_ioctl *
|
||||
*===========================================================================*/
|
||||
static int fbd_ioctl(dev_t UNUSED(minor), unsigned int request,
|
||||
endpoint_t endpt, cp_grant_id_t grant)
|
||||
static int fbd_ioctl(devminor_t UNUSED(minor), unsigned long request,
|
||||
endpoint_t endpt, cp_grant_id_t grant, endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
/* Handle an I/O control request. */
|
||||
cp_grant_id_t gid;
|
||||
|
|
@ -222,6 +215,7 @@ static int fbd_ioctl(dev_t UNUSED(minor), unsigned int request,
|
|||
m.BDEV_MINOR = driver_minor;
|
||||
m.BDEV_REQUEST = request;
|
||||
m.BDEV_GRANT = gid;
|
||||
m.BDEV_USER = NONE;
|
||||
m.BDEV_ID = 0;
|
||||
|
||||
if ((r = sendrec(driver_endpt, &m)) != OK)
|
||||
|
|
@ -406,11 +400,11 @@ static ssize_t fbd_transfer_copy(int do_write, u64_t position,
|
|||
/*===========================================================================*
|
||||
* fbd_transfer *
|
||||
*===========================================================================*/
|
||||
static int fbd_transfer(dev_t UNUSED(minor), int do_write, u64_t position,
|
||||
static int fbd_transfer(devminor_t UNUSED(minor), int do_write, u64_t position,
|
||||
endpoint_t endpt, iovec_t *iov, unsigned int nr_req, int flags)
|
||||
{
|
||||
/* Transfer data from or to the device. */
|
||||
unsigned count;
|
||||
unsigned int count;
|
||||
size_t size, osize;
|
||||
int i, hooks;
|
||||
ssize_t r;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ static int driver_open(int which)
|
|||
memset(&msg, 0, sizeof(msg));
|
||||
msg.m_type = BDEV_OPEN;
|
||||
msg.BDEV_MINOR = driver[which].minor;
|
||||
msg.BDEV_ACCESS = R_BIT | W_BIT;
|
||||
msg.BDEV_ACCESS = BDEV_R_BIT | BDEV_W_BIT;
|
||||
msg.BDEV_ID = 0;
|
||||
r = sendrec(driver[which].endpt, &msg);
|
||||
|
||||
|
|
@ -60,6 +60,7 @@ static int driver_open(int which)
|
|||
msg.BDEV_MINOR = driver[which].minor;
|
||||
msg.BDEV_REQUEST = DIOCGETP;
|
||||
msg.BDEV_GRANT = gid;
|
||||
msg.BDEV_USER = NONE;
|
||||
msg.BDEV_ID = 0;
|
||||
|
||||
r = sendrec(driver[which].endpt, &msg);
|
||||
|
|
|
|||
|
|
@ -63,12 +63,6 @@ static struct optset optset_table[] = {
|
|||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
/* Request message. */
|
||||
static message m_in;
|
||||
static endpoint_t who_e; /* m_source */
|
||||
static long req_id; /* BDEV_ID */
|
||||
static cp_grant_id_t grant_id; /* BDEV_GRANT */
|
||||
|
||||
/* Data buffers. */
|
||||
static char *buf_array, *buffer; /* contiguous buffer */
|
||||
|
||||
|
|
@ -77,26 +71,46 @@ static void sef_local_startup(void);
|
|||
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
|
||||
static void sef_cb_signal_handler(int signo);
|
||||
|
||||
/*===========================================================================*
|
||||
* carry *
|
||||
*===========================================================================*/
|
||||
static int carry(size_t size, int flag_rw)
|
||||
{
|
||||
/* Carry data between caller proc and filter.
|
||||
*/
|
||||
static int filter_open(devminor_t minor, int access);
|
||||
static int filter_close(devminor_t minor);
|
||||
static ssize_t filter_transfer(devminor_t minor, int do_write, u64_t pos,
|
||||
endpoint_t endpt, iovec_t *iov, unsigned int count, int flags);
|
||||
static int filter_ioctl(devminor_t minor, unsigned long request,
|
||||
endpoint_t endpt, cp_grant_id_t grant, endpoint_t user_endpt);
|
||||
static void filter_other(message *m, int ipc_status);
|
||||
|
||||
if (flag_rw == FLT_WRITE)
|
||||
return sys_safecopyfrom(who_e, grant_id, 0,
|
||||
(vir_bytes) buffer, size);
|
||||
else
|
||||
return sys_safecopyto(who_e, grant_id, 0,
|
||||
(vir_bytes) buffer, size);
|
||||
static struct blockdriver filter_tab = {
|
||||
.bdr_type = BLOCKDRIVER_TYPE_OTHER,
|
||||
.bdr_open = filter_open,
|
||||
.bdr_close = filter_close,
|
||||
.bdr_transfer = filter_transfer,
|
||||
.bdr_ioctl = filter_ioctl,
|
||||
.bdr_other = filter_other
|
||||
};
|
||||
|
||||
/*===========================================================================*
|
||||
* filter_open *
|
||||
*===========================================================================*/
|
||||
static int filter_open(devminor_t UNUSED(minor), int UNUSED(access))
|
||||
{
|
||||
/* Open is a noop for filter. */
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* filter_close *
|
||||
*===========================================================================*/
|
||||
static int filter_close(devminor_t UNUSED(minor))
|
||||
{
|
||||
/* Close is a noop for filter. */
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* vcarry *
|
||||
*===========================================================================*/
|
||||
static int vcarry(int grants, iovec_t *iov, int flag_rw, size_t size)
|
||||
static int vcarry(endpoint_t endpt, unsigned int grants, iovec_t *iov,
|
||||
int do_write, size_t size)
|
||||
{
|
||||
/* Carry data between caller proc and filter, through grant-vector.
|
||||
*/
|
||||
|
|
@ -108,12 +122,12 @@ static int vcarry(int grants, iovec_t *iov, int flag_rw, size_t size)
|
|||
for(i = 0; i < grants && size > 0; i++) {
|
||||
bytes = MIN(size, iov[i].iov_size);
|
||||
|
||||
if (flag_rw == FLT_WRITE)
|
||||
r = sys_safecopyfrom(who_e,
|
||||
if (do_write)
|
||||
r = sys_safecopyfrom(endpt,
|
||||
(vir_bytes) iov[i].iov_addr, 0,
|
||||
(vir_bytes) bufp, bytes);
|
||||
else
|
||||
r = sys_safecopyto(who_e,
|
||||
r = sys_safecopyto(endpt,
|
||||
(vir_bytes) iov[i].iov_addr, 0,
|
||||
(vir_bytes) bufp, bytes);
|
||||
|
||||
|
|
@ -127,76 +141,19 @@ static int vcarry(int grants, iovec_t *iov, int flag_rw, size_t size)
|
|||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_rdwt *
|
||||
*===========================================================================*/
|
||||
static int do_rdwt(int flag_rw)
|
||||
{
|
||||
size_t size, size_ret;
|
||||
u64_t pos;
|
||||
int r;
|
||||
|
||||
pos = make64(m_in.BDEV_POS_LO, m_in.BDEV_POS_HI);
|
||||
size = m_in.BDEV_COUNT;
|
||||
|
||||
if (rem64u(pos, SECTOR_SIZE) != 0 || size % SECTOR_SIZE != 0) {
|
||||
printf("Filter: unaligned request from caller!\n");
|
||||
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
buffer = flt_malloc(size, buf_array, BUF_SIZE);
|
||||
|
||||
if(flag_rw == FLT_WRITE)
|
||||
carry(size, flag_rw);
|
||||
|
||||
reset_kills();
|
||||
|
||||
for (;;) {
|
||||
size_ret = size;
|
||||
r = transfer(pos, buffer, &size_ret, flag_rw);
|
||||
if(r != RET_REDO)
|
||||
break;
|
||||
|
||||
#if DEBUG
|
||||
printf("Filter: transfer yielded RET_REDO, checking drivers\n");
|
||||
#endif
|
||||
if((r = check_driver(DRIVER_MAIN)) != OK) break;
|
||||
if((r = check_driver(DRIVER_BACKUP)) != OK) break;
|
||||
}
|
||||
|
||||
if(r == OK && flag_rw == FLT_READ)
|
||||
carry(size_ret, flag_rw);
|
||||
|
||||
flt_free(buffer, size, buf_array);
|
||||
|
||||
if (r != OK)
|
||||
return r;
|
||||
|
||||
return size_ret;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_vrdwt *
|
||||
* filter_transfer *
|
||||
*===========================================================================*/
|
||||
static int do_vrdwt(int flag_rw)
|
||||
static ssize_t filter_transfer(devminor_t UNUSED(minor), int do_write,
|
||||
u64_t pos, endpoint_t endpt, iovec_t *iov, unsigned int count,
|
||||
int UNUSED(flags))
|
||||
{
|
||||
size_t size, size_ret;
|
||||
int grants;
|
||||
int r, i;
|
||||
u64_t pos;
|
||||
iovec_t iov_proc[NR_IOREQS];
|
||||
|
||||
/* Extract informations. */
|
||||
grants = m_in.BDEV_COUNT;
|
||||
if((r = sys_safecopyfrom(who_e, grant_id, 0, (vir_bytes) iov_proc,
|
||||
grants * sizeof(iovec_t))) != OK) {
|
||||
panic("copying in grant vector failed: %d", r);
|
||||
}
|
||||
|
||||
pos = make64(m_in.BDEV_POS_LO, m_in.BDEV_POS_HI);
|
||||
for(size = 0, i = 0; i < grants; i++)
|
||||
size += iov_proc[i].iov_size;
|
||||
for(size = 0, i = 0; i < count; i++)
|
||||
size += iov[i].iov_size;
|
||||
|
||||
if (rem64u(pos, SECTOR_SIZE) != 0 || size % SECTOR_SIZE != 0) {
|
||||
printf("Filter: unaligned request from caller!\n");
|
||||
|
|
@ -205,14 +162,15 @@ static int do_vrdwt(int flag_rw)
|
|||
|
||||
buffer = flt_malloc(size, buf_array, BUF_SIZE);
|
||||
|
||||
if(flag_rw == FLT_WRITE)
|
||||
vcarry(grants, iov_proc, flag_rw, size);
|
||||
if (do_write)
|
||||
vcarry(endpt, count, iov, do_write, size);
|
||||
|
||||
reset_kills();
|
||||
|
||||
for (;;) {
|
||||
size_ret = size;
|
||||
r = transfer(pos, buffer, &size_ret, flag_rw);
|
||||
r = transfer(pos, buffer, &size_ret,
|
||||
do_write ? FLT_WRITE : FLT_READ);
|
||||
if(r != RET_REDO)
|
||||
break;
|
||||
|
||||
|
|
@ -228,8 +186,8 @@ static int do_vrdwt(int flag_rw)
|
|||
return r;
|
||||
}
|
||||
|
||||
if(flag_rw == FLT_READ)
|
||||
vcarry(grants, iov_proc, flag_rw, size_ret);
|
||||
if (!do_write)
|
||||
vcarry(endpt, count, iov, do_write, size_ret);
|
||||
|
||||
flt_free(buffer, size, buf_array);
|
||||
|
||||
|
|
@ -237,13 +195,14 @@ static int do_vrdwt(int flag_rw)
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_ioctl *
|
||||
* filter_ioctl *
|
||||
*===========================================================================*/
|
||||
static int do_ioctl(message *m)
|
||||
static int filter_ioctl(devminor_t UNUSED(minor), unsigned long request,
|
||||
endpoint_t endpt, cp_grant_id_t grant, endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
struct part_geom sizepart;
|
||||
|
||||
switch(m->BDEV_REQUEST) {
|
||||
switch (request) {
|
||||
case DIOCSETP:
|
||||
case DIOCTIMEOUT:
|
||||
case DIOCOPENCT:
|
||||
|
|
@ -258,8 +217,7 @@ static int do_ioctl(message *m)
|
|||
*/
|
||||
sizepart.size = convert(get_raw_size());
|
||||
|
||||
if(sys_safecopyto(who_e, (vir_bytes) grant_id, 0,
|
||||
(vir_bytes) &sizepart,
|
||||
if (sys_safecopyto(endpt, grant, 0, (vir_bytes) &sizepart,
|
||||
sizeof(struct part_geom)) != OK) {
|
||||
printf("Filter: DIOCGETP safecopyto failed\n");
|
||||
return EIO;
|
||||
|
|
@ -267,14 +225,24 @@ static int do_ioctl(message *m)
|
|||
break;
|
||||
|
||||
default:
|
||||
printf("Filter: unknown ioctl request: %d!\n",
|
||||
m->BDEV_REQUEST);
|
||||
return EINVAL;
|
||||
printf("Filter: unknown ioctl request: %ld!\n", request);
|
||||
return ENOTTY;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* filter_other *
|
||||
*===========================================================================*/
|
||||
static void filter_other(message *m, int ipc_status)
|
||||
{
|
||||
/* Process other messages. */
|
||||
if (m->m_source == DS_PROC_NR && is_ipc_notify(ipc_status)) {
|
||||
ds_event();
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* parse_arguments *
|
||||
*===========================================================================*/
|
||||
|
|
@ -371,53 +339,7 @@ int main(int argc, char *argv[])
|
|||
env_setargs(argc, argv);
|
||||
sef_local_startup();
|
||||
|
||||
for (;;) {
|
||||
/* Wait for request. */
|
||||
if(driver_receive(ANY, &m_in, &ipc_status) != OK) {
|
||||
panic("driver_receive failed");
|
||||
}
|
||||
|
||||
#if DEBUG2
|
||||
printf("Filter: got request %d from %d\n",
|
||||
m_in.m_type, m_in.m_source);
|
||||
#endif
|
||||
|
||||
if(m_in.m_source == DS_PROC_NR && is_ipc_notify(ipc_status)) {
|
||||
ds_event();
|
||||
continue;
|
||||
}
|
||||
|
||||
who_e = m_in.m_source;
|
||||
req_id = m_in.BDEV_ID;
|
||||
grant_id = m_in.BDEV_GRANT;
|
||||
size = 0;
|
||||
|
||||
/* Forword the request message to the drivers. */
|
||||
switch(m_in.m_type) {
|
||||
case BDEV_OPEN: /* open/close is a noop for filter. */
|
||||
case BDEV_CLOSE: r = OK; break;
|
||||
case BDEV_READ: r = do_rdwt(FLT_READ); break;
|
||||
case BDEV_WRITE: r = do_rdwt(FLT_WRITE); break;
|
||||
case BDEV_GATHER: r = do_vrdwt(FLT_READ); break;
|
||||
case BDEV_SCATTER: r = do_vrdwt(FLT_WRITE); break;
|
||||
case BDEV_IOCTL: r = do_ioctl(&m_in); break;
|
||||
|
||||
default:
|
||||
printf("Filter: ignoring unknown request %d from %d\n",
|
||||
m_in.m_type, m_in.m_source);
|
||||
continue;
|
||||
}
|
||||
|
||||
#if DEBUG2
|
||||
printf("Filter: replying with code %d\n", r);
|
||||
#endif
|
||||
|
||||
/* Send back reply message. */
|
||||
m_out.m_type = BDEV_REPLY;
|
||||
m_out.BDEV_ID = req_id;
|
||||
m_out.BDEV_STATUS = r;
|
||||
send(who_e, &m_out);
|
||||
}
|
||||
blockdriver_task(&filter_tab);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -490,4 +412,3 @@ static void sef_cb_signal_handler(int signo)
|
|||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -242,10 +242,10 @@ static void f_expire_tmrs(clock_t stamp);
|
|||
static void stop_motor(timer_t *tp);
|
||||
static void f_timeout(timer_t *tp);
|
||||
|
||||
static struct device *f_prepare(dev_t device);
|
||||
static struct device *f_part(dev_t minor);
|
||||
static struct device *f_prepare(devminor_t device);
|
||||
static struct device *f_part(devminor_t minor);
|
||||
static void f_cleanup(void);
|
||||
static ssize_t f_transfer(dev_t minor, int do_write, u64_t position,
|
||||
static ssize_t f_transfer(devminor_t minor, int do_write, u64_t position,
|
||||
endpoint_t proc_nr, iovec_t *iov, unsigned int nr_req, int flags);
|
||||
static int dma_setup(int do_write);
|
||||
static void start_motor(void);
|
||||
|
|
@ -258,25 +258,21 @@ static int recalibrate(void);
|
|||
static void f_reset(void);
|
||||
static int f_intr_wait(void);
|
||||
static int read_id(void);
|
||||
static int f_do_open(dev_t minor, int access);
|
||||
static int f_do_close(dev_t minor);
|
||||
static int f_do_open(devminor_t minor, int access);
|
||||
static int f_do_close(devminor_t minor);
|
||||
static int test_read(int density);
|
||||
static void f_geometry(dev_t minor, struct part_geom *entry);
|
||||
static void f_geometry(devminor_t minor, struct part_geom *entry);
|
||||
|
||||
/* Entry points to this driver. */
|
||||
static struct blockdriver f_dtab = {
|
||||
BLOCKDRIVER_TYPE_DISK, /* handle partition requests */
|
||||
f_do_open, /* open or mount request, sense type of diskette */
|
||||
f_do_close, /* nothing on a close */
|
||||
f_transfer, /* do the I/O */
|
||||
NULL, /* no other I/O control requests are supported */
|
||||
f_cleanup, /* cleanup before sending reply to user process */
|
||||
f_part, /* return partition information structure */
|
||||
f_geometry, /* tell the geometry of the diskette */
|
||||
NULL, /* no processing of hardware interrupts */
|
||||
f_expire_tmrs,/* expire all alarm timers */
|
||||
NULL, /* no processing of other messages */
|
||||
NULL /* no threading support */
|
||||
.bdr_type = BLOCKDRIVER_TYPE_DISK, /* handle partition requests */
|
||||
.bdr_open = f_do_open, /* open request, sense type of diskette */
|
||||
.bdr_close = f_do_close, /* nothing on a close */
|
||||
.bdr_transfer = f_transfer, /* do the I/O */
|
||||
.bdr_cleanup = f_cleanup, /* cleanup before sending reply to caller */
|
||||
.bdr_part = f_part, /* return partition information structure */
|
||||
.bdr_geometry = f_geometry, /* tell the geometry of the diskette */
|
||||
.bdr_alarm = f_expire_tmrs /* expire all alarm timers */
|
||||
};
|
||||
|
||||
static char *floppy_buf;
|
||||
|
|
@ -397,13 +393,13 @@ static void f_expire_tmrs(clock_t stamp)
|
|||
/*===========================================================================*
|
||||
* f_prepare *
|
||||
*===========================================================================*/
|
||||
static struct device *f_prepare(dev_t device)
|
||||
static struct device *f_prepare(devminor_t device)
|
||||
{
|
||||
/* Prepare for I/O on a device. */
|
||||
|
||||
f_device = device;
|
||||
f_drive = device & ~(DEV_TYPE_BITS | FORMAT_DEV_BIT);
|
||||
if (f_drive >= NR_DRIVES) return(NULL);
|
||||
if (device < 0 || f_drive >= NR_DRIVES) return(NULL);
|
||||
|
||||
f_fp = &floppy[f_drive];
|
||||
f_dv = &f_fp->fl_geom;
|
||||
|
|
@ -424,7 +420,7 @@ static struct device *f_prepare(dev_t device)
|
|||
/*===========================================================================*
|
||||
* f_part *
|
||||
*===========================================================================*/
|
||||
static struct device *f_part(dev_t minor)
|
||||
static struct device *f_part(devminor_t minor)
|
||||
{
|
||||
/* Return a pointer to the partition information of the given minor device. */
|
||||
|
||||
|
|
@ -447,7 +443,7 @@ static void f_cleanup(void)
|
|||
* f_transfer *
|
||||
*===========================================================================*/
|
||||
static ssize_t f_transfer(
|
||||
dev_t minor, /* minor device number */
|
||||
devminor_t minor, /* minor device number */
|
||||
int do_write, /* read or write? */
|
||||
u64_t pos64, /* offset on device to read or write */
|
||||
endpoint_t proc_nr, /* process doing the request */
|
||||
|
|
@ -1251,7 +1247,7 @@ static int read_id(void)
|
|||
/*===========================================================================*
|
||||
* f_do_open *
|
||||
*===========================================================================*/
|
||||
static int f_do_open(dev_t minor, int UNUSED(access))
|
||||
static int f_do_open(devminor_t minor, int UNUSED(access))
|
||||
{
|
||||
/* Handle an open on a floppy. Determine diskette type if need be. */
|
||||
|
||||
|
|
@ -1310,7 +1306,7 @@ static int f_do_open(dev_t minor, int UNUSED(access))
|
|||
/*===========================================================================*
|
||||
* f_do_close *
|
||||
*===========================================================================*/
|
||||
static int f_do_close(dev_t UNUSED(minor))
|
||||
static int f_do_close(devminor_t UNUSED(minor))
|
||||
{
|
||||
/* Handle a close on a floppy. Nothing to do here. */
|
||||
|
||||
|
|
@ -1350,7 +1346,7 @@ static int test_read(int density)
|
|||
/*===========================================================================*
|
||||
* f_geometry *
|
||||
*===========================================================================*/
|
||||
static void f_geometry(dev_t minor, struct part_geom *entry)
|
||||
static void f_geometry(devminor_t minor, struct part_geom *entry)
|
||||
{
|
||||
if (f_prepare(minor) == NULL) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,12 +8,10 @@
|
|||
/*
|
||||
* Function prototypes for the hello driver.
|
||||
*/
|
||||
static int hello_open(message *m);
|
||||
static int hello_close(message *m);
|
||||
static struct device * hello_prepare(dev_t device);
|
||||
static int hello_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t *iov, unsigned int nr_req, endpoint_t user_endpt, unsigned int
|
||||
flags);
|
||||
static int hello_open(devminor_t minor, int access, endpoint_t user_endpt);
|
||||
static int hello_close(devminor_t minor);
|
||||
static ssize_t hello_read(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
|
||||
/* SEF functions and variables. */
|
||||
static void sef_local_startup(void);
|
||||
|
|
@ -24,77 +22,54 @@ static int lu_state_restore(void);
|
|||
/* Entry points to the hello driver. */
|
||||
static struct chardriver hello_tab =
|
||||
{
|
||||
hello_open,
|
||||
hello_close,
|
||||
nop_ioctl,
|
||||
hello_prepare,
|
||||
hello_transfer,
|
||||
nop_cleanup,
|
||||
nop_alarm,
|
||||
nop_cancel,
|
||||
nop_select,
|
||||
NULL
|
||||
.cdr_open = hello_open,
|
||||
.cdr_close = hello_close,
|
||||
.cdr_read = hello_read,
|
||||
};
|
||||
|
||||
/** Represents the /dev/hello device. */
|
||||
static struct device hello_device;
|
||||
|
||||
/** State variable to count the number of times the device has been opened. */
|
||||
/** State variable to count the number of times the device has been opened.
|
||||
* Note that this is not the regular type of open counter: it never decreases.
|
||||
*/
|
||||
static int open_counter;
|
||||
|
||||
static int hello_open(message *UNUSED(m))
|
||||
static int hello_open(devminor_t UNUSED(minor), int UNUSED(access),
|
||||
endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
printf("hello_open(). Called %d time(s).\n", ++open_counter);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int hello_close(message *UNUSED(m))
|
||||
static int hello_close(devminor_t UNUSED(minor))
|
||||
{
|
||||
printf("hello_close()\n");
|
||||
return OK;
|
||||
}
|
||||
|
||||
static struct device * hello_prepare(dev_t UNUSED(dev))
|
||||
static ssize_t hello_read(devminor_t UNUSED(minor), u64_t position,
|
||||
endpoint_t endpt, cp_grant_id_t grant, size_t size, int UNUSED(flags),
|
||||
cdev_id_t UNUSED(id))
|
||||
{
|
||||
hello_device.dv_base = make64(0, 0);
|
||||
hello_device.dv_size = make64(strlen(HELLO_MESSAGE), 0);
|
||||
return &hello_device;
|
||||
}
|
||||
u64_t dev_size;
|
||||
char *ptr;
|
||||
int ret;
|
||||
|
||||
static int hello_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t *iov, unsigned nr_req, endpoint_t UNUSED(user_endpt),
|
||||
unsigned int UNUSED(flags))
|
||||
{
|
||||
int bytes, ret;
|
||||
printf("hello_read()\n");
|
||||
|
||||
printf("hello_transfer()\n");
|
||||
/* This is the total size of our device. */
|
||||
dev_size = (u64_t) strlen(HELLO_MESSAGE);
|
||||
|
||||
if (nr_req != 1)
|
||||
{
|
||||
/* This should never trigger for character drivers at the moment. */
|
||||
printf("HELLO: vectored transfer request, using first element only\n");
|
||||
}
|
||||
/* Check for EOF, and possibly limit the read size. */
|
||||
if (position >= dev_size) return 0; /* EOF */
|
||||
if (position + size > dev_size)
|
||||
size = (size_t)(dev_size - position); /* limit size */
|
||||
|
||||
bytes = strlen(HELLO_MESSAGE) - ex64lo(position) < iov->iov_size ?
|
||||
strlen(HELLO_MESSAGE) - ex64lo(position) : iov->iov_size;
|
||||
/* Copy the requested part to the caller. */
|
||||
ptr = HELLO_MESSAGE + (size_t)position;
|
||||
if ((ret = sys_safecopyto(endpt, grant, 0, (vir_bytes) ptr, size)) != OK)
|
||||
return ret;
|
||||
|
||||
if (bytes <= 0)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
switch (opcode)
|
||||
{
|
||||
case DEV_GATHER_S:
|
||||
ret = sys_safecopyto(endpt, (cp_grant_id_t) iov->iov_addr, 0,
|
||||
(vir_bytes) (HELLO_MESSAGE + ex64lo(position)),
|
||||
bytes);
|
||||
iov->iov_size -= bytes;
|
||||
break;
|
||||
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
return ret;
|
||||
/* Return the number of bytes read. */
|
||||
return size;
|
||||
}
|
||||
|
||||
static int sef_cb_lu_state_save(int UNUSED(state)) {
|
||||
|
|
@ -181,7 +156,7 @@ int main(void)
|
|||
/*
|
||||
* Run the main loop.
|
||||
*/
|
||||
chardriver_task(&hello_tab, CHARDRIVER_SYNC);
|
||||
chardriver_task(&hello_tab);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,16 +33,14 @@ static void update_reservation(endpoint_t endpt, char *key);
|
|||
static void ds_event(void);
|
||||
|
||||
static int validate_ioctl_exec(minix_i2c_ioctl_exec_t * ioctl_exec);
|
||||
static int do_i2c_ioctl_exec(message * m);
|
||||
static int do_i2c_ioctl_exec(endpoint_t caller, cp_grant_id_t grant_nr);
|
||||
|
||||
static int env_parse_instance(void);
|
||||
|
||||
/* libchardriver callbacks */
|
||||
int i2c_ioctl(message * m);
|
||||
struct device *i2c_prepare(dev_t dev);
|
||||
int i2c_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t * iov, unsigned nr_req, endpoint_t user_endpt, unsigned int flags);
|
||||
int i2c_other(message * m);
|
||||
static int i2c_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
|
||||
cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id);
|
||||
static void i2c_other(message * m, int ipc_status);
|
||||
|
||||
/* SEF callbacks and driver state management */
|
||||
static int sef_cb_lu_state_save(int);
|
||||
|
|
@ -68,8 +66,6 @@ static struct i2cdev
|
|||
*/
|
||||
int (*process) (minix_i2c_ioctl_exec_t * ioctl_exec);
|
||||
|
||||
struct device i2c_device;
|
||||
|
||||
/* logging - use with log_warn(), log_info(), log_debug(), log_trace() */
|
||||
static struct log log = {
|
||||
.name = "i2c",
|
||||
|
|
@ -81,16 +77,8 @@ static struct log log = {
|
|||
* Only i2c_ioctl() and i2c_other() are implemented. The rest are no-op.
|
||||
*/
|
||||
static struct chardriver i2c_tab = {
|
||||
.cdr_open = do_nop,
|
||||
.cdr_close = do_nop,
|
||||
.cdr_ioctl = i2c_ioctl,
|
||||
.cdr_prepare = i2c_prepare,
|
||||
.cdr_transfer = i2c_transfer,
|
||||
.cdr_cleanup = nop_cleanup,
|
||||
.cdr_alarm = nop_alarm,
|
||||
.cdr_cancel = nop_cancel,
|
||||
.cdr_select = nop_select,
|
||||
.cdr_other = i2c_other
|
||||
.cdr_ioctl = i2c_ioctl,
|
||||
.cdr_other = i2c_other
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -232,14 +220,14 @@ validate_ioctl_exec(minix_i2c_ioctl_exec_t * ioctl_exec)
|
|||
}
|
||||
|
||||
len = ioctl_exec->iie_cmdlen;
|
||||
if (len < 0 || len > I2C_EXEC_MAX_CMDLEN) {
|
||||
if (len > I2C_EXEC_MAX_CMDLEN) {
|
||||
log_warn(&log,
|
||||
"iie_cmdlen out of range 0-I2C_EXEC_MAX_CMDLEN\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
len = ioctl_exec->iie_buflen;
|
||||
if (len < 0 || len > I2C_EXEC_MAX_BUFLEN) {
|
||||
if (len > I2C_EXEC_MAX_BUFLEN) {
|
||||
log_warn(&log,
|
||||
"iie_buflen out of range 0-I2C_EXEC_MAX_BUFLEN\n");
|
||||
return EINVAL;
|
||||
|
|
@ -252,16 +240,11 @@ validate_ioctl_exec(minix_i2c_ioctl_exec_t * ioctl_exec)
|
|||
* Performs the action in minix_i2c_ioctl_exec_t.
|
||||
*/
|
||||
static int
|
||||
do_i2c_ioctl_exec(message * m)
|
||||
do_i2c_ioctl_exec(endpoint_t caller, cp_grant_id_t grant_nr)
|
||||
{
|
||||
int r;
|
||||
endpoint_t caller;
|
||||
cp_grant_id_t grant_nr;
|
||||
minix_i2c_ioctl_exec_t ioctl_exec;
|
||||
|
||||
caller = (endpoint_t) m->m_source;
|
||||
grant_nr = (cp_grant_id_t) m->IO_GRANT;
|
||||
|
||||
/* Copy the requested exection into the driver */
|
||||
r = sys_safecopyfrom(caller, grant_nr, (vir_bytes) 0,
|
||||
(vir_bytes) & ioctl_exec, sizeof(ioctl_exec));
|
||||
|
|
@ -302,45 +285,48 @@ do_i2c_ioctl_exec(message * m)
|
|||
return OK;
|
||||
}
|
||||
|
||||
int
|
||||
i2c_ioctl(message * m)
|
||||
static int
|
||||
i2c_ioctl(devminor_t UNUSED(minor), unsigned long request, endpoint_t endpt,
|
||||
cp_grant_id_t grant, int UNUSED(flags), endpoint_t UNUSED(user_endpt),
|
||||
cdev_id_t UNUSED(id))
|
||||
{
|
||||
int r;
|
||||
|
||||
switch (m->COUNT) {
|
||||
switch (request) {
|
||||
case MINIX_I2C_IOCTL_EXEC:
|
||||
r = do_i2c_ioctl_exec(m);
|
||||
r = do_i2c_ioctl_exec(endpt, grant);
|
||||
break;
|
||||
default:
|
||||
log_warn(&log, "Invalid ioctl() 0x%x\n", m->COUNT);
|
||||
r = EINVAL;
|
||||
log_warn(&log, "Invalid ioctl() 0x%x\n", request);
|
||||
r = ENOTTY;
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
i2c_other(message * m)
|
||||
static void
|
||||
i2c_other(message * m, int ipc_status)
|
||||
{
|
||||
message m_reply;
|
||||
int r;
|
||||
|
||||
switch (m->m_type) {
|
||||
case BUSC_I2C_RESERVE:
|
||||
/* reserve a device on the bus for exclusive access */
|
||||
r = do_reserve((endpoint_t) m->m_source, m->DEVICE);
|
||||
break;
|
||||
case BUSC_I2C_EXEC:
|
||||
/* handle request from another driver */
|
||||
m->COUNT = MINIX_I2C_IOCTL_EXEC;
|
||||
r = do_i2c_ioctl_exec(m);
|
||||
break;
|
||||
case NOTIFY_MESSAGE:
|
||||
if (is_ipc_notify(ipc_status)) {
|
||||
/* handle notifications about drivers changing state */
|
||||
if (m->m_source == DS_PROC_NR) {
|
||||
ds_event();
|
||||
}
|
||||
r = OK;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (m->m_type) {
|
||||
case BUSC_I2C_RESERVE:
|
||||
/* reserve a device on the bus for exclusive access */
|
||||
r = do_reserve(m->m_source, m->BUSC_I2C_ADDR);
|
||||
break;
|
||||
case BUSC_I2C_EXEC:
|
||||
/* handle request from another driver */
|
||||
r = do_i2c_ioctl_exec(m->m_source, m->BUSC_I2C_GRANT);
|
||||
break;
|
||||
default:
|
||||
log_warn(&log, "Invalid message type (0x%x)\n", m->m_type);
|
||||
|
|
@ -350,25 +336,12 @@ i2c_other(message * m)
|
|||
|
||||
log_trace(&log, "i2c_other() returning r=%d\n", r);
|
||||
|
||||
return r;
|
||||
}
|
||||
/* Send a reply. */
|
||||
memset(&m_reply, 0, sizeof(m_reply));
|
||||
m_reply.m_type = r;
|
||||
|
||||
struct device *
|
||||
i2c_prepare(dev_t dev)
|
||||
{
|
||||
/* NOP */
|
||||
i2c_device.dv_base = make64(0, 0);
|
||||
i2c_device.dv_size = make64(0, 0);
|
||||
|
||||
return &i2c_device;
|
||||
}
|
||||
|
||||
int
|
||||
i2c_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t * iov, unsigned nr_req, endpoint_t user_endpt, unsigned int flags)
|
||||
{
|
||||
/* NOP */
|
||||
return OK;
|
||||
if ((r = send(m->m_source, &m_reply)) != OK)
|
||||
log_warn(&log, "send() to %d failed: %d\n", m->m_source, r);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -549,7 +522,7 @@ main(int argc, char *argv[])
|
|||
|
||||
memset(i2cdev, '\0', sizeof(i2cdev));
|
||||
sef_local_startup();
|
||||
chardriver_task(&i2c_tab, CHARDRIVER_SYNC);
|
||||
chardriver_task(&i2c_tab);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,32 +19,24 @@
|
|||
#define LOGINC(n, i) do { (n) = (((n) + (i)) % LOG_SIZE); } while(0)
|
||||
|
||||
struct logdevice logdevices[NR_DEVS];
|
||||
static struct device log_geom[NR_DEVS]; /* base and size of devices */
|
||||
static int log_device = -1; /* current device */
|
||||
|
||||
static struct device *log_prepare(dev_t device);
|
||||
static int log_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t *iov, unsigned int nr_req, endpoint_t user_endpt, unsigned int
|
||||
flags);
|
||||
static int log_do_open(message *m_ptr);
|
||||
static int log_cancel(message *m_ptr);
|
||||
static int log_select(message *m_ptr);
|
||||
static int log_other(message *m_ptr);
|
||||
static int subread(struct logdevice *log, int count, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t);
|
||||
static ssize_t log_read(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
static ssize_t log_write(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
static int log_open(devminor_t minor, int access, endpoint_t user_endpt);
|
||||
static int log_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id);
|
||||
static int log_select(devminor_t minor, unsigned int ops, endpoint_t endpt);
|
||||
static int subread(struct logdevice *log, size_t size, endpoint_t endpt,
|
||||
cp_grant_id_t grant);
|
||||
|
||||
/* Entry points to this driver. */
|
||||
static struct chardriver log_dtab = {
|
||||
log_do_open, /* open or mount */
|
||||
do_nop, /* nothing on a close */
|
||||
nop_ioctl, /* ioctl nop */
|
||||
log_prepare, /* prepare for I/O on a given minor device */
|
||||
log_transfer, /* do the I/O */
|
||||
nop_cleanup, /* no need to clean up */
|
||||
nop_alarm, /* no alarm */
|
||||
log_cancel, /* CANCEL request */
|
||||
log_select, /* DEV_SELECT request */
|
||||
log_other /* Unrecognized messages */
|
||||
.cdr_open = log_open,
|
||||
.cdr_read = log_read,
|
||||
.cdr_write = log_write,
|
||||
.cdr_cancel = log_cancel,
|
||||
.cdr_select = log_select
|
||||
};
|
||||
|
||||
/* SEF functions and variables. */
|
||||
|
|
@ -64,7 +56,7 @@ int main(void)
|
|||
sef_local_startup();
|
||||
|
||||
/* Call the generic receive loop. */
|
||||
chardriver_task(&log_dtab, CHARDRIVER_ASYNC);
|
||||
chardriver_task(&log_dtab);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
|
@ -101,17 +93,15 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
|||
|
||||
/* Initialize log devices. */
|
||||
for(i = 0; i < NR_DEVS; i++) {
|
||||
log_geom[i].dv_size = ((u64_t)(LOG_SIZE));
|
||||
log_geom[i].dv_base = ((u64_t)((long)logdevices[i].log_buffer));
|
||||
logdevices[i].log_size = logdevices[i].log_read =
|
||||
logdevices[i].log_write =
|
||||
logdevices[i].log_select_alerted =
|
||||
logdevices[i].log_selected =
|
||||
logdevices[i].log_select_ready_ops = 0;
|
||||
logdevices[i].log_selected = 0;
|
||||
logdevices[i].log_source = NONE;
|
||||
logdevices[i].log_revive_alerted = 0;
|
||||
}
|
||||
|
||||
/* Register for diagnostics notifications. */
|
||||
sys_diagctl_register();
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
|
@ -126,29 +116,24 @@ static void sef_cb_signal_handler(int signo)
|
|||
do_new_kmess();
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* log_prepare *
|
||||
*===========================================================================*/
|
||||
static struct device *log_prepare(dev_t device)
|
||||
{
|
||||
/* Prepare for I/O on a device: check if the minor device number is ok. */
|
||||
|
||||
if (device >= NR_DEVS) return(NULL);
|
||||
log_device = (int) device;
|
||||
|
||||
return(&log_geom[device]);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* subwrite *
|
||||
*===========================================================================*/
|
||||
static int
|
||||
subwrite(struct logdevice *log, int count, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t offset, char *localbuf)
|
||||
subwrite(struct logdevice *log, size_t size, endpoint_t endpt,
|
||||
cp_grant_id_t grant, char *localbuf)
|
||||
{
|
||||
int d, r;
|
||||
char *buf;
|
||||
message m;
|
||||
size_t count, offset;
|
||||
int overflow, r;
|
||||
devminor_t minor;
|
||||
char *buf;
|
||||
message m;
|
||||
|
||||
/* With a sufficiently large input size, we might wrap around the ring buffer
|
||||
* multiple times.
|
||||
*/
|
||||
for (offset = 0; offset < size; offset += count) {
|
||||
count = size - offset;
|
||||
|
||||
if (log->log_write + count > LOG_SIZE)
|
||||
count = LOG_SIZE - log->log_write;
|
||||
|
|
@ -156,75 +141,49 @@ subwrite(struct logdevice *log, int count, endpoint_t endpt,
|
|||
|
||||
if(localbuf != NULL) {
|
||||
memcpy(buf, localbuf, count);
|
||||
localbuf += count;
|
||||
}
|
||||
else {
|
||||
if((r=sys_safecopyfrom(endpt, grant, offset,
|
||||
(vir_bytes)buf, count)) != OK)
|
||||
return r;
|
||||
break; /* do process partial write upon error */
|
||||
}
|
||||
|
||||
LOGINC(log->log_write, count);
|
||||
log->log_size += count;
|
||||
|
||||
if(log->log_size > LOG_SIZE) {
|
||||
int overflow;
|
||||
overflow = log->log_size - LOG_SIZE;
|
||||
log->log_size -= overflow;
|
||||
LOGINC(log->log_read, overflow);
|
||||
}
|
||||
|
||||
if(log->log_size > 0 && log->log_source != NONE &&
|
||||
!log->log_revive_alerted) {
|
||||
/* Someone who was suspended on read can now
|
||||
* be revived.
|
||||
*/
|
||||
log->log_status = subread(log, log->log_iosize,
|
||||
log->log_source, log->log_user_grant,
|
||||
log->log_user_offset);
|
||||
r = offset; /* this will be the return value upon success */
|
||||
}
|
||||
|
||||
m.m_type = DEV_REVIVE;
|
||||
m.REP_ENDPT = log->log_proc_nr;
|
||||
m.REP_STATUS = log->log_status;
|
||||
m.REP_IO_GRANT = log->log_user_grant;
|
||||
r= send(log->log_source, &m);
|
||||
if (r != OK)
|
||||
{
|
||||
printf("log`subwrite: send to %d failed: %d\n",
|
||||
log->log_source, r);
|
||||
}
|
||||
log->log_source = NONE;
|
||||
}
|
||||
if (log->log_size > 0 && log->log_source != NONE) {
|
||||
/* Someone who was suspended on read can now be revived. */
|
||||
r = subread(log, log->log_iosize, log->log_source, log->log_grant);
|
||||
|
||||
if(log->log_size > 0)
|
||||
log->log_select_ready_ops |= SEL_RD;
|
||||
chardriver_reply_task(log->log_source, log->log_id, r);
|
||||
|
||||
if(log->log_size > 0 && log->log_selected &&
|
||||
!(log->log_select_alerted)) {
|
||||
/* Someone(s) who was/were select()ing can now
|
||||
* be awoken. If there was a blocking read (above),
|
||||
* this can only happen if the blocking read didn't
|
||||
* swallow all the data (log_size > 0).
|
||||
*/
|
||||
if(log->log_selected & SEL_RD) {
|
||||
d= log-logdevices;
|
||||
m.m_type = DEV_SEL_REPL2;
|
||||
m.DEV_SEL_OPS = log->log_select_ready_ops;
|
||||
m.DEV_MINOR = d;
|
||||
log->log_source = NONE;
|
||||
}
|
||||
|
||||
if (log->log_size > 0 && (log->log_selected & CDEV_OP_RD)) {
|
||||
/* Someone(s) who was/were select()ing can now be awoken. If there was
|
||||
* a blocking read (above), this can only happen if the blocking read
|
||||
* didn't swallow all the data (log_size > 0).
|
||||
*/
|
||||
minor = log-logdevices;
|
||||
#if LOG_DEBUG
|
||||
printf("select sending DEV_SEL_REPL2\n");
|
||||
printf("select sending CDEV_SEL2_REPLY\n");
|
||||
#endif
|
||||
r= send(log->log_select_proc, &m);
|
||||
if (r != OK)
|
||||
{
|
||||
printf(
|
||||
"log`subwrite: send to %d failed: %d\n",
|
||||
log->log_select_proc, r);
|
||||
}
|
||||
log->log_selected &= ~log->log_select_ready_ops;
|
||||
}
|
||||
}
|
||||
chardriver_reply_select(log->log_select_proc, minor, CDEV_OP_RD);
|
||||
log->log_selected &= ~CDEV_OP_RD;
|
||||
}
|
||||
|
||||
return count;
|
||||
return r;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
@ -233,210 +192,156 @@ subwrite(struct logdevice *log, int count, endpoint_t endpt,
|
|||
void
|
||||
log_append(char *buf, int count)
|
||||
{
|
||||
int w = 0, skip = 0;
|
||||
int skip = 0;
|
||||
|
||||
if(count < 1) return;
|
||||
if(count > LOG_SIZE) skip = count - LOG_SIZE;
|
||||
count -= skip;
|
||||
buf += skip;
|
||||
w = subwrite(&logdevices[0], count, SELF, GRANT_INVALID, 0, buf);
|
||||
if(count < 1) return;
|
||||
if(count > LOG_SIZE) skip = count - LOG_SIZE;
|
||||
count -= skip;
|
||||
buf += skip;
|
||||
|
||||
if(w > 0 && w < count)
|
||||
subwrite(&logdevices[0], count-w, SELF, GRANT_INVALID, 0,
|
||||
buf + w);
|
||||
return;
|
||||
subwrite(&logdevices[0], count, SELF, GRANT_INVALID, buf);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* subread *
|
||||
*===========================================================================*/
|
||||
static int
|
||||
subread(struct logdevice *log, int count, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t offset)
|
||||
subread(struct logdevice *log, size_t size, endpoint_t endpt,
|
||||
cp_grant_id_t grant)
|
||||
{
|
||||
char *buf;
|
||||
int r;
|
||||
size_t offset, count;
|
||||
char *buf;
|
||||
int r;
|
||||
|
||||
for (offset = 0; log->log_size > 0 && offset < size; offset += count) {
|
||||
count = size - offset;
|
||||
|
||||
if (count > log->log_size)
|
||||
count = log->log_size;
|
||||
if (log->log_read + count > LOG_SIZE)
|
||||
count = LOG_SIZE - log->log_read;
|
||||
|
||||
buf = log->log_buffer + log->log_read;
|
||||
if((r=sys_safecopyto(endpt, grant, offset,
|
||||
(vir_bytes)buf, count)) != OK)
|
||||
if((r=sys_safecopyto(endpt, grant, offset, (vir_bytes)buf,
|
||||
count)) != OK)
|
||||
return r;
|
||||
|
||||
LOGINC(log->log_read, count);
|
||||
log->log_size -= count;
|
||||
}
|
||||
|
||||
return count;
|
||||
return offset;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* log_transfer *
|
||||
* log_read *
|
||||
*===========================================================================*/
|
||||
static int log_transfer(
|
||||
endpoint_t endpt, /* endpoint of grant owner */
|
||||
int opcode, /* DEV_GATHER_S or DEV_SCATTER_S */
|
||||
u64_t UNUSED(position), /* offset on device to read or write */
|
||||
iovec_t *iov, /* pointer to read or write request vector */
|
||||
unsigned int nr_req, /* length of request vector */
|
||||
endpoint_t user_endpt, /* endpoint of user process */
|
||||
unsigned int UNUSED(flags)
|
||||
)
|
||||
static ssize_t log_read(devminor_t minor, u64_t UNUSED(position),
|
||||
endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
|
||||
cdev_id_t id)
|
||||
{
|
||||
/* Read or write one the driver's minor devices. */
|
||||
int count;
|
||||
cp_grant_id_t grant;
|
||||
int accumulated_read = 0;
|
||||
/* Read from one of the driver's minor devices. */
|
||||
struct logdevice *log;
|
||||
size_t vir_offset = 0;
|
||||
int r;
|
||||
|
||||
if(log_device < 0 || log_device >= NR_DEVS)
|
||||
return EIO;
|
||||
if (minor < 0 || minor >= NR_DEVS) return EIO;
|
||||
log = &logdevices[minor];
|
||||
|
||||
/* Get minor device number and check for /dev/null. */
|
||||
log = &logdevices[log_device];
|
||||
/* If there's already someone hanging to read, don't accept new work. */
|
||||
if (log->log_source != NONE) return OK;
|
||||
|
||||
while (nr_req > 0) {
|
||||
/* How much to transfer and where to / from. */
|
||||
count = iov->iov_size;
|
||||
grant = iov->iov_addr;
|
||||
if (!log->log_size && size > 0) {
|
||||
if (flags & CDEV_NONBLOCK) return EAGAIN;
|
||||
|
||||
switch (log_device) {
|
||||
|
||||
case MINOR_KLOG:
|
||||
if (opcode == DEV_GATHER_S) {
|
||||
if (log->log_source != NONE || count < 1) {
|
||||
/* There's already someone hanging to read, or
|
||||
* no real I/O requested.
|
||||
*/
|
||||
return(OK);
|
||||
}
|
||||
|
||||
if (!log->log_size) {
|
||||
if(accumulated_read)
|
||||
return OK;
|
||||
/* No data available; let caller block. */
|
||||
log->log_source = endpt;
|
||||
log->log_iosize = count;
|
||||
log->log_user_grant = grant;
|
||||
log->log_user_offset = 0;
|
||||
log->log_revive_alerted = 0;
|
||||
log->log_proc_nr = user_endpt;
|
||||
/* No data available; let caller block. */
|
||||
log->log_source = endpt;
|
||||
log->log_iosize = size;
|
||||
log->log_grant = grant;
|
||||
log->log_id = id;
|
||||
#if LOG_DEBUG
|
||||
printf("blocked %d (%d)\n",
|
||||
log->log_source, log->log_proc_nr);
|
||||
printf("blocked %d (%d)\n", log->log_source, id);
|
||||
#endif
|
||||
return(EDONTREPLY);
|
||||
}
|
||||
count = subread(log, count, endpt, grant, vir_offset);
|
||||
if(count < 0) {
|
||||
return count;
|
||||
}
|
||||
accumulated_read += count;
|
||||
} else {
|
||||
count = subwrite(log, count, endpt, grant, vir_offset, NULL);
|
||||
if(count < 0)
|
||||
return count;
|
||||
}
|
||||
break;
|
||||
/* Unknown (illegal) minor device. */
|
||||
default:
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
/* Book the number of bytes transferred. */
|
||||
vir_offset += count;
|
||||
if ((iov->iov_size -= count) == 0) { iov++; nr_req--; vir_offset = 0; }
|
||||
return EDONTREPLY;
|
||||
}
|
||||
return(OK);
|
||||
|
||||
return subread(log, size, endpt, grant);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* log_write *
|
||||
*===========================================================================*/
|
||||
static ssize_t log_write(devminor_t minor, u64_t UNUSED(position),
|
||||
endpoint_t endpt, cp_grant_id_t grant, size_t size, int UNUSED(flags),
|
||||
cdev_id_t UNUSED(id))
|
||||
{
|
||||
/* Write to one of the driver's minor devices. */
|
||||
struct logdevice *log;
|
||||
int r;
|
||||
|
||||
if (minor < 0 || minor >= NR_DEVS) return EIO;
|
||||
log = &logdevices[minor];
|
||||
|
||||
return subwrite(log, size, endpt, grant, NULL);
|
||||
}
|
||||
|
||||
/*============================================================================*
|
||||
* log_do_open *
|
||||
* log_open *
|
||||
*============================================================================*/
|
||||
static int log_do_open(message *m_ptr)
|
||||
static int log_open(devminor_t minor, int UNUSED(access),
|
||||
endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
if (log_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
|
||||
if (minor < 0 || minor >= NR_DEVS) return(ENXIO);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/*============================================================================*
|
||||
* log_cancel *
|
||||
*============================================================================*/
|
||||
static int log_cancel(message *m_ptr)
|
||||
static int log_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id)
|
||||
{
|
||||
int d;
|
||||
d = m_ptr->TTY_LINE;
|
||||
if(d < 0 || d >= NR_DEVS)
|
||||
if (minor < 0 || minor >= NR_DEVS)
|
||||
return EINVAL;
|
||||
logdevices[d].log_proc_nr = NONE;
|
||||
logdevices[d].log_revive_alerted = 0;
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/*============================================================================*
|
||||
* log_other *
|
||||
*============================================================================*/
|
||||
static int log_other(message *m_ptr)
|
||||
{
|
||||
int r;
|
||||
/* Not for the suspended request? Must be a stale cancel request. Ignore. */
|
||||
if (logdevices[minor].log_source != endpt || logdevices[minor].log_id != id)
|
||||
return EDONTREPLY;
|
||||
|
||||
/* This function gets messages that the generic driver doesn't
|
||||
* understand.
|
||||
*/
|
||||
if (is_notify(m_ptr->m_type)) {
|
||||
return EINVAL;
|
||||
}
|
||||
logdevices[minor].log_source = NONE;
|
||||
|
||||
switch(m_ptr->m_type) {
|
||||
case DEV_STATUS: {
|
||||
printf("log_other: unexpected DEV_STATUS request\n");
|
||||
r = EDONTREPLY;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
r = EINVAL;
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
return EINTR; /* this is the reply to the original, interrupted request */
|
||||
}
|
||||
|
||||
/*============================================================================*
|
||||
* log_select *
|
||||
*============================================================================*/
|
||||
static int log_select(message *m_ptr)
|
||||
static int log_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
|
||||
{
|
||||
int d, ready_ops = 0, ops = 0;
|
||||
d = m_ptr->TTY_LINE;
|
||||
if(d < 0 || d >= NR_DEVS) {
|
||||
#if LOG_DEBUG
|
||||
printf("line %d? EINVAL\n", d);
|
||||
#endif
|
||||
return EINVAL;
|
||||
}
|
||||
int want_ops, ready_ops = 0;
|
||||
|
||||
ops = m_ptr->USER_ENDPT & (SEL_RD|SEL_WR|SEL_ERR);
|
||||
if (minor < 0 || minor >= NR_DEVS)
|
||||
return ENXIO;
|
||||
|
||||
want_ops = ops & (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR);
|
||||
|
||||
/* Read blocks when there is no log. */
|
||||
if((m_ptr->USER_ENDPT & SEL_RD) && logdevices[d].log_size > 0) {
|
||||
if ((want_ops & CDEV_OP_RD) && logdevices[minor].log_size > 0) {
|
||||
#if LOG_DEBUG
|
||||
printf("log can read; size %d\n", logdevices[d].log_size);
|
||||
printf("log can read; size %d\n", logdevices[minor].log_size);
|
||||
#endif
|
||||
ready_ops |= SEL_RD; /* writes never block */
|
||||
ready_ops |= CDEV_OP_RD;
|
||||
}
|
||||
|
||||
/* Write never blocks. */
|
||||
if(m_ptr->USER_ENDPT & SEL_WR) ready_ops |= SEL_WR;
|
||||
if (want_ops & CDEV_OP_WR) ready_ops |= CDEV_OP_WR;
|
||||
|
||||
/* Enable select calback if no operations were
|
||||
* ready to go, but operations were requested,
|
||||
* and notify was enabled.
|
||||
*/
|
||||
if((m_ptr->USER_ENDPT & SEL_NOTIFY) && ops && !ready_ops) {
|
||||
logdevices[d].log_selected |= ops;
|
||||
logdevices[d].log_select_proc = m_ptr->m_source;
|
||||
/* Enable select calback if not all requested operations were ready to go,
|
||||
* and notify was enabled.
|
||||
*/
|
||||
want_ops &= ~ready_ops;
|
||||
if ((ops & CDEV_NOTIFY) && want_ops) {
|
||||
logdevices[minor].log_selected |= want_ops;
|
||||
logdevices[minor].log_select_proc = endpt;
|
||||
#if LOG_DEBUG
|
||||
printf("log setting selector.\n");
|
||||
#endif
|
||||
|
|
@ -448,4 +353,3 @@ static int log_select(message *m_ptr)
|
|||
|
||||
return(ready_ops);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,24 +10,18 @@
|
|||
/* Constants and types. */
|
||||
|
||||
#define LOG_SIZE (50*1024)
|
||||
#define SUSPENDABLE 1
|
||||
|
||||
struct logdevice {
|
||||
char log_buffer[LOG_SIZE];
|
||||
int log_size, /* no. of bytes in log buffer */
|
||||
log_read, /* read mark */
|
||||
log_write; /* write mark */
|
||||
#if SUSPENDABLE
|
||||
endpoint_t log_proc_nr,
|
||||
log_source;
|
||||
endpoint_t log_source;
|
||||
cdev_id_t log_id;
|
||||
int log_iosize,
|
||||
log_revive_alerted,
|
||||
log_status;
|
||||
cp_grant_id_t log_user_grant;
|
||||
vir_bytes log_user_offset;
|
||||
#endif
|
||||
int log_selected, log_select_proc,
|
||||
log_select_alerted, log_select_ready_ops;
|
||||
cp_grant_id_t log_grant;
|
||||
int log_selected, log_select_proc;
|
||||
};
|
||||
|
||||
/* Function prototypes. */
|
||||
|
|
|
|||
|
|
@ -41,63 +41,46 @@
|
|||
|
||||
static struct device m_geom[NR_DEVS]; /* base and size of each device */
|
||||
static vir_bytes m_vaddrs[NR_DEVS];
|
||||
static dev_t m_device; /* current minor character device */
|
||||
|
||||
static int openct[NR_DEVS];
|
||||
|
||||
static struct device *m_prepare(dev_t device);
|
||||
static int m_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t *iov, unsigned int nr_req, endpoint_t user_endpt, unsigned int
|
||||
flags);
|
||||
static int m_do_open(message *m_ptr);
|
||||
static int m_do_close(message *m_ptr);
|
||||
static ssize_t m_char_read(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
static ssize_t m_char_write(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
static int m_char_open(devminor_t minor, int access, endpoint_t user_endpt);
|
||||
static int m_char_close(devminor_t minor);
|
||||
|
||||
static struct device *m_block_part(dev_t minor);
|
||||
static int m_block_transfer(dev_t minor, int do_write, u64_t position,
|
||||
static struct device *m_block_part(devminor_t minor);
|
||||
static ssize_t m_block_transfer(devminor_t minor, int do_write, u64_t position,
|
||||
endpoint_t endpt, iovec_t *iov, unsigned int nr_req, int flags);
|
||||
static int m_block_open(dev_t minor, int access);
|
||||
static int m_block_close(dev_t minor);
|
||||
static int m_block_ioctl(dev_t minor, unsigned int request, endpoint_t
|
||||
endpt, cp_grant_id_t grant);
|
||||
static int m_block_open(devminor_t minor, int access);
|
||||
static int m_block_close(devminor_t minor);
|
||||
static int m_block_ioctl(devminor_t minor, unsigned long request, endpoint_t
|
||||
endpt, cp_grant_id_t grant, endpoint_t user_endpt);
|
||||
|
||||
/* Entry points to the CHARACTER part of this driver. */
|
||||
static struct chardriver m_cdtab = {
|
||||
m_do_open, /* open or mount */
|
||||
m_do_close, /* nothing on a close */
|
||||
nop_ioctl, /* no I/O control */
|
||||
m_prepare, /* prepare for I/O on a given minor device */
|
||||
m_transfer, /* do the I/O */
|
||||
nop_cleanup, /* no need to clean up */
|
||||
nop_alarm, /* no alarms */
|
||||
nop_cancel, /* no blocking operations */
|
||||
nop_select, /* select not supported */
|
||||
NULL /* other messages not supported */
|
||||
.cdr_open = m_char_open, /* open device */
|
||||
.cdr_close = m_char_close, /* close device */
|
||||
.cdr_read = m_char_read, /* read from device */
|
||||
.cdr_write = m_char_write /* write to device */
|
||||
};
|
||||
|
||||
/* Entry points to the BLOCK part of this driver. */
|
||||
static struct blockdriver m_bdtab = {
|
||||
BLOCKDRIVER_TYPE_DISK,/* handle partition requests */
|
||||
m_block_open, /* open or mount */
|
||||
m_block_close, /* nothing on a close */
|
||||
m_block_transfer, /* do the I/O */
|
||||
m_block_ioctl, /* ram disk I/O control */
|
||||
NULL, /* no need to clean up */
|
||||
m_block_part, /* return partition information */
|
||||
NULL, /* no geometry */
|
||||
NULL, /* no interrupt processing */
|
||||
NULL, /* no alarm processing */
|
||||
NULL, /* no processing of other messages */
|
||||
NULL /* no threading support */
|
||||
.bdr_type = BLOCKDRIVER_TYPE_DISK,/* handle partition requests */
|
||||
.bdr_open = m_block_open, /* open device */
|
||||
.bdr_close = m_block_close, /* nothing on a close */
|
||||
.bdr_transfer = m_block_transfer, /* do the I/O */
|
||||
.bdr_ioctl = m_block_ioctl, /* ram disk I/O control */
|
||||
.bdr_part = m_block_part /* return partition information */
|
||||
};
|
||||
|
||||
#define click_to_round_k(n) \
|
||||
((unsigned) ((((unsigned long) (n) << CLICK_SHIFT) + 512) / 1024))
|
||||
|
||||
/* SEF functions and variables. */
|
||||
static void sef_local_startup(void);
|
||||
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* main *
|
||||
*===========================================================================*/
|
||||
|
|
@ -117,8 +100,7 @@ int main(void)
|
|||
if (IS_BDEV_RQ(msg.m_type))
|
||||
blockdriver_process(&m_bdtab, &msg, ipc_status);
|
||||
else
|
||||
chardriver_process(&m_cdtab, CHARDRIVER_SYNC, &msg,
|
||||
ipc_status);
|
||||
chardriver_process(&m_cdtab, &msg, ipc_status);
|
||||
}
|
||||
|
||||
return(OK);
|
||||
|
|
@ -158,8 +140,8 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
|||
}
|
||||
|
||||
/* Map in kernel memory for /dev/kmem. */
|
||||
m_geom[KMEM_DEV].dv_base = cvul64(kinfo.kmem_base);
|
||||
m_geom[KMEM_DEV].dv_size = cvul64(kinfo.kmem_size);
|
||||
m_geom[KMEM_DEV].dv_base = kinfo.kmem_base;
|
||||
m_geom[KMEM_DEV].dv_size = kinfo.kmem_size;
|
||||
if((m_vaddrs[KMEM_DEV] = vm_map_phys(SELF, (void *) kinfo.kmem_base,
|
||||
kinfo.kmem_size)) == MAP_FAILED) {
|
||||
printf("MEM: Couldn't map in /dev/kmem.");
|
||||
|
|
@ -167,16 +149,16 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
|||
#endif
|
||||
|
||||
/* Ramdisk image built into the memory driver */
|
||||
m_geom[IMGRD_DEV].dv_base= ((u64_t)(0));
|
||||
m_geom[IMGRD_DEV].dv_size= ((u64_t)(imgrd_size));
|
||||
m_geom[IMGRD_DEV].dv_base= 0;
|
||||
m_geom[IMGRD_DEV].dv_size= imgrd_size;
|
||||
m_vaddrs[IMGRD_DEV] = (vir_bytes) imgrd;
|
||||
|
||||
for(i = 0; i < NR_DEVS; i++)
|
||||
openct[i] = 0;
|
||||
|
||||
/* Set up memory range for /dev/mem. */
|
||||
m_geom[MEM_DEV].dv_base = ((u64_t)(0));
|
||||
m_geom[MEM_DEV].dv_size = ((u64_t)(0xffffffff));
|
||||
m_geom[MEM_DEV].dv_base = 0;
|
||||
m_geom[MEM_DEV].dv_size = 0xffffffffULL;
|
||||
|
||||
m_vaddrs[MEM_DEV] = (vir_bytes) MAP_FAILED; /* we are not mapping this in. */
|
||||
|
||||
|
|
@ -186,7 +168,7 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
|||
/*===========================================================================*
|
||||
* m_is_block *
|
||||
*===========================================================================*/
|
||||
static int m_is_block(dev_t minor)
|
||||
static int m_is_block(devminor_t minor)
|
||||
{
|
||||
/* Return TRUE iff the given minor device number is for a block device. */
|
||||
|
||||
|
|
@ -203,206 +185,218 @@ static int m_is_block(dev_t minor)
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* m_prepare *
|
||||
* m_transfer_kmem *
|
||||
*===========================================================================*/
|
||||
static struct device *m_prepare(dev_t device)
|
||||
static ssize_t m_transfer_kmem(devminor_t minor, int do_write, u64_t position,
|
||||
endpoint_t endpt, cp_grant_id_t grant, size_t size)
|
||||
{
|
||||
/* Prepare for I/O on a device: check if the minor device number is ok. */
|
||||
if (device >= NR_DEVS || m_is_block(device)) return(NULL);
|
||||
m_device = device;
|
||||
|
||||
return(&m_geom[device]);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* m_transfer *
|
||||
*===========================================================================*/
|
||||
static int m_transfer(
|
||||
endpoint_t endpt, /* endpoint of grant owner */
|
||||
int opcode, /* DEV_GATHER_S or DEV_SCATTER_S */
|
||||
u64_t pos64, /* offset on device to read or write */
|
||||
iovec_t *iov, /* pointer to read or write request vector */
|
||||
unsigned int nr_req, /* length of request vector */
|
||||
endpoint_t UNUSED(user_endpt),/* endpoint of user process */
|
||||
unsigned int UNUSED(flags)
|
||||
)
|
||||
{
|
||||
/* Read or write one the driver's character devices. */
|
||||
unsigned count;
|
||||
vir_bytes vir_offset = 0;
|
||||
struct device *dv;
|
||||
u64_t dv_size;
|
||||
int s, r;
|
||||
u64_t position;
|
||||
cp_grant_id_t grant;
|
||||
vir_bytes dev_vaddr;
|
||||
|
||||
/* ZERO_DEV and NULL_DEV are infinite in size. */
|
||||
if (m_device != ZERO_DEV && m_device != NULL_DEV && ex64hi(pos64) != 0)
|
||||
return OK; /* Beyond EOF */
|
||||
position= pos64;
|
||||
|
||||
/* Get minor device number and check for /dev/null. */
|
||||
dv = &m_geom[m_device];
|
||||
dv_size = dv->dv_size;
|
||||
dev_vaddr = m_vaddrs[m_device];
|
||||
|
||||
while (nr_req > 0) {
|
||||
|
||||
/* How much to transfer and where to / from. */
|
||||
count = iov->iov_size;
|
||||
grant = (cp_grant_id_t) iov->iov_addr;
|
||||
|
||||
switch (m_device) {
|
||||
|
||||
/* No copying; ignore request. */
|
||||
case NULL_DEV:
|
||||
if (opcode == DEV_GATHER_S) return(OK); /* always at EOF */
|
||||
break;
|
||||
|
||||
/* Virtual copying. For kernel memory. */
|
||||
default:
|
||||
case KMEM_DEV:
|
||||
if(!dev_vaddr || dev_vaddr == (vir_bytes) MAP_FAILED) {
|
||||
printf("MEM: dev %d not initialized\n", m_device);
|
||||
return EIO;
|
||||
}
|
||||
if (position >= dv_size) return(OK); /* check for EOF */
|
||||
if (position + count > dv_size) count = dv_size - position;
|
||||
if (opcode == DEV_GATHER_S) { /* copy actual data */
|
||||
r=sys_safecopyto(endpt, grant, vir_offset,
|
||||
dev_vaddr + position, count);
|
||||
} else {
|
||||
r=sys_safecopyfrom(endpt, grant, vir_offset,
|
||||
dev_vaddr + position, count);
|
||||
}
|
||||
if(r != OK) {
|
||||
panic("I/O copy failed: %d", r);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Physical copying. Only used to access entire memory.
|
||||
* Transfer one 'page window' at a time.
|
||||
*/
|
||||
case MEM_DEV:
|
||||
{
|
||||
u32_t pagestart, page_off;
|
||||
static u32_t pagestart_mapped;
|
||||
static int any_mapped = 0;
|
||||
static char *vaddr;
|
||||
int r;
|
||||
u32_t subcount;
|
||||
phys_bytes mem_phys;
|
||||
|
||||
if (position >= dv_size)
|
||||
return(OK); /* check for EOF */
|
||||
if (position + count > dv_size)
|
||||
count = dv_size - position;
|
||||
mem_phys = position;
|
||||
|
||||
page_off = mem_phys % PAGE_SIZE;
|
||||
pagestart = mem_phys - page_off;
|
||||
|
||||
/* All memory to the map call has to be page-aligned.
|
||||
* Don't have to map same page over and over.
|
||||
*/
|
||||
if(!any_mapped || pagestart_mapped != pagestart) {
|
||||
if(any_mapped) {
|
||||
if(vm_unmap_phys(SELF, vaddr, PAGE_SIZE) != OK)
|
||||
panic("vm_unmap_phys failed");
|
||||
any_mapped = 0;
|
||||
}
|
||||
vaddr = vm_map_phys(SELF, (void *) pagestart, PAGE_SIZE);
|
||||
if(vaddr == MAP_FAILED)
|
||||
r = ENOMEM;
|
||||
else
|
||||
r = OK;
|
||||
if(r != OK) {
|
||||
printf("memory: vm_map_phys failed\n");
|
||||
return r;
|
||||
}
|
||||
any_mapped = 1;
|
||||
pagestart_mapped = pagestart;
|
||||
}
|
||||
|
||||
/* how much to be done within this page. */
|
||||
subcount = PAGE_SIZE-page_off;
|
||||
if(subcount > count)
|
||||
subcount = count;
|
||||
|
||||
if (opcode == DEV_GATHER_S) { /* copy data */
|
||||
s=sys_safecopyto(endpt, grant,
|
||||
vir_offset, (vir_bytes) vaddr+page_off, subcount);
|
||||
} else {
|
||||
s=sys_safecopyfrom(endpt, grant,
|
||||
vir_offset, (vir_bytes) vaddr+page_off, subcount);
|
||||
}
|
||||
if(s != OK)
|
||||
return s;
|
||||
count = subcount;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Null byte stream generator. */
|
||||
case ZERO_DEV:
|
||||
if (opcode == DEV_GATHER_S)
|
||||
if ((s = sys_safememset(endpt, grant, 0, '\0', count)) != OK)
|
||||
return s;
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* Book the number of bytes transferred. */
|
||||
position += count;
|
||||
vir_offset += count;
|
||||
if ((iov->iov_size -= count) == 0) { iov++; nr_req--; vir_offset = 0; }
|
||||
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* m_do_open *
|
||||
*===========================================================================*/
|
||||
static int m_do_open(message *m_ptr)
|
||||
{
|
||||
/* Open a memory character device. */
|
||||
/* Transfer from or to the KMEM device. */
|
||||
u64_t dv_size, dev_vaddr;
|
||||
int r;
|
||||
|
||||
/* Check device number on open. */
|
||||
if (m_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
|
||||
dv_size = m_geom[minor].dv_size;
|
||||
dev_vaddr = m_vaddrs[minor];
|
||||
|
||||
if (!dev_vaddr || dev_vaddr == (vir_bytes) MAP_FAILED) {
|
||||
printf("MEM: dev %d not initialized\n", minor);
|
||||
return EIO;
|
||||
}
|
||||
|
||||
if (position >= dv_size) return 0; /* check for EOF */
|
||||
if (position + size > dv_size) size = dv_size - position;
|
||||
|
||||
if (!do_write) /* copy actual data */
|
||||
r = sys_safecopyto(endpt, grant, 0, dev_vaddr + position, size);
|
||||
else
|
||||
r = sys_safecopyfrom(endpt, grant, 0, dev_vaddr + position, size);
|
||||
|
||||
return (r != OK) ? r : size;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* m_transfer_mem *
|
||||
*===========================================================================*/
|
||||
static ssize_t m_transfer_mem(devminor_t minor, int do_write, u64_t position,
|
||||
endpoint_t endpt, cp_grant_id_t grant, size_t size)
|
||||
{
|
||||
/* Transfer from or to the MEM device. */
|
||||
static int any_mapped = 0;
|
||||
static phys_bytes pagestart_mapped;
|
||||
static char *vaddr;
|
||||
phys_bytes mem_phys, pagestart;
|
||||
size_t off, page_off, subcount;
|
||||
u64_t dv_size;
|
||||
int r;
|
||||
|
||||
dv_size = m_geom[minor].dv_size;
|
||||
if (position >= dv_size) return 0; /* check for EOF */
|
||||
if (position + size > dv_size) size = dv_size - position;
|
||||
|
||||
/* Physical copying. Only used to access entire memory.
|
||||
* Transfer one 'page window' at a time.
|
||||
*/
|
||||
off = 0;
|
||||
while (off < size) {
|
||||
mem_phys = (phys_bytes) position;
|
||||
|
||||
page_off = (size_t) (mem_phys % PAGE_SIZE);
|
||||
pagestart = mem_phys - page_off;
|
||||
|
||||
/* All memory to the map call has to be page-aligned.
|
||||
* Don't have to map same page over and over.
|
||||
*/
|
||||
if (!any_mapped || pagestart_mapped != pagestart) {
|
||||
if (any_mapped) {
|
||||
if (vm_unmap_phys(SELF, vaddr, PAGE_SIZE) != OK)
|
||||
panic("vm_unmap_phys failed");
|
||||
any_mapped = 0;
|
||||
}
|
||||
|
||||
vaddr = vm_map_phys(SELF, (void *) pagestart, PAGE_SIZE);
|
||||
if (vaddr == MAP_FAILED) {
|
||||
printf("memory: vm_map_phys failed\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
any_mapped = 1;
|
||||
pagestart_mapped = pagestart;
|
||||
}
|
||||
|
||||
/* how much to be done within this page. */
|
||||
subcount = PAGE_SIZE - page_off;
|
||||
if (subcount > size)
|
||||
subcount = size;
|
||||
|
||||
if (!do_write) /* copy data */
|
||||
r = sys_safecopyto(endpt, grant, off,
|
||||
(vir_bytes) vaddr + page_off, subcount);
|
||||
else
|
||||
r = sys_safecopyfrom(endpt, grant, off,
|
||||
(vir_bytes) vaddr + page_off, subcount);
|
||||
if (r != OK)
|
||||
return r;
|
||||
|
||||
position += subcount;
|
||||
off += subcount;
|
||||
}
|
||||
|
||||
return off;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* m_char_read *
|
||||
*===========================================================================*/
|
||||
static ssize_t m_char_read(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int UNUSED(flags),
|
||||
cdev_id_t UNUSED(id))
|
||||
{
|
||||
/* Read from one of the driver's character devices. */
|
||||
ssize_t r;
|
||||
|
||||
/* Check if the minor device number is ok. */
|
||||
if (minor < 0 || minor >= NR_DEVS || m_is_block(minor)) return ENXIO;
|
||||
|
||||
switch (minor) {
|
||||
case NULL_DEV:
|
||||
r = 0; /* always at EOF */
|
||||
break;
|
||||
|
||||
case ZERO_DEV:
|
||||
/* Fill the target area with zeroes. In fact, let the kernel do it! */
|
||||
if ((r = sys_safememset(endpt, grant, 0, '\0', size)) == OK)
|
||||
r = size;
|
||||
break;
|
||||
|
||||
case KMEM_DEV:
|
||||
r = m_transfer_kmem(minor, FALSE, position, endpt, grant, size);
|
||||
break;
|
||||
|
||||
case MEM_DEV:
|
||||
r = m_transfer_mem(minor, FALSE, position, endpt, grant, size);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("unknown character device %d", minor);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* m_char_write *
|
||||
*===========================================================================*/
|
||||
static ssize_t m_char_write(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int UNUSED(flags),
|
||||
cdev_id_t UNUSED(id))
|
||||
{
|
||||
/* Write to one of the driver's character devices. */
|
||||
ssize_t r;
|
||||
|
||||
/* Check if the minor device number is ok. */
|
||||
if (minor < 0 || minor >= NR_DEVS || m_is_block(minor)) return ENXIO;
|
||||
|
||||
switch (minor) {
|
||||
case NULL_DEV:
|
||||
case ZERO_DEV:
|
||||
r = size; /* just eat everything */
|
||||
break;
|
||||
|
||||
case KMEM_DEV:
|
||||
r = m_transfer_kmem(minor, TRUE, position, endpt, grant, size);
|
||||
break;
|
||||
|
||||
case MEM_DEV:
|
||||
r = m_transfer_mem(minor, TRUE, position, endpt, grant, size);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("unknown character device %d", minor);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* m_char_open *
|
||||
*===========================================================================*/
|
||||
static int m_char_open(devminor_t minor, int access, endpoint_t user_endpt)
|
||||
{
|
||||
/* Open a memory character device. */
|
||||
|
||||
/* Check if the minor device number is ok. */
|
||||
if (minor < 0 || minor >= NR_DEVS || m_is_block(minor)) return ENXIO;
|
||||
|
||||
#if defined(__i386__)
|
||||
if (m_device == MEM_DEV)
|
||||
if (minor == MEM_DEV)
|
||||
{
|
||||
r = sys_enable_iop(m_ptr->USER_ENDPT);
|
||||
int r = sys_enable_iop(user_endpt);
|
||||
if (r != OK)
|
||||
{
|
||||
printf("m_do_open: sys_enable_iop failed for %d: %d\n",
|
||||
m_ptr->USER_ENDPT, r);
|
||||
printf("m_char_open: sys_enable_iop failed for %d: %d\n",
|
||||
user_endpt, r);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
openct[m_device]++;
|
||||
openct[minor]++;
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* m_do_close *
|
||||
* m_char_close *
|
||||
*===========================================================================*/
|
||||
static int m_do_close(message *m_ptr)
|
||||
static int m_char_close(devminor_t minor)
|
||||
{
|
||||
/* Close a memory character device. */
|
||||
if (m_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
|
||||
|
||||
if(openct[m_device] < 1) {
|
||||
printf("MEMORY: closing unopened device %d\n", m_device);
|
||||
if (minor < 0 || minor >= NR_DEVS || m_is_block(minor)) return ENXIO;
|
||||
|
||||
if(openct[minor] < 1) {
|
||||
printf("MEMORY: closing unopened device %d\n", minor);
|
||||
return(EINVAL);
|
||||
}
|
||||
openct[m_device]--;
|
||||
openct[minor]--;
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
|
@ -410,10 +404,10 @@ static int m_do_close(message *m_ptr)
|
|||
/*===========================================================================*
|
||||
* m_block_part *
|
||||
*===========================================================================*/
|
||||
static struct device *m_block_part(dev_t minor)
|
||||
static struct device *m_block_part(devminor_t minor)
|
||||
{
|
||||
/* Prepare for I/O on a device: check if the minor device number is ok. */
|
||||
if (minor >= NR_DEVS || !m_is_block(minor)) return(NULL);
|
||||
if (minor < 0 || minor >= NR_DEVS || !m_is_block(minor)) return(NULL);
|
||||
|
||||
return(&m_geom[minor]);
|
||||
}
|
||||
|
|
@ -422,9 +416,9 @@ static struct device *m_block_part(dev_t minor)
|
|||
* m_block_transfer *
|
||||
*===========================================================================*/
|
||||
static int m_block_transfer(
|
||||
dev_t minor, /* minor device number */
|
||||
devminor_t minor, /* minor device number */
|
||||
int do_write, /* read or write? */
|
||||
u64_t pos64, /* offset on device to read or write */
|
||||
u64_t position, /* offset on device to read or write */
|
||||
endpoint_t endpt, /* process doing the request */
|
||||
iovec_t *iov, /* pointer to read or write request vector */
|
||||
unsigned int nr_req, /* length of request vector */
|
||||
|
|
@ -437,7 +431,6 @@ static int m_block_transfer(
|
|||
struct device *dv;
|
||||
u64_t dv_size;
|
||||
int r;
|
||||
u64_t position;
|
||||
vir_bytes dev_vaddr;
|
||||
cp_grant_id_t grant;
|
||||
ssize_t total = 0;
|
||||
|
|
@ -447,9 +440,8 @@ static int m_block_transfer(
|
|||
dv_size = dv->dv_size;
|
||||
dev_vaddr = m_vaddrs[minor];
|
||||
|
||||
if (ex64hi(pos64) != 0)
|
||||
if (ex64hi(position) != 0)
|
||||
return OK; /* Beyond EOF */
|
||||
position= pos64;
|
||||
|
||||
while (nr_req > 0) {
|
||||
|
||||
|
|
@ -488,7 +480,7 @@ static int m_block_transfer(
|
|||
/*===========================================================================*
|
||||
* m_block_open *
|
||||
*===========================================================================*/
|
||||
static int m_block_open(dev_t minor, int UNUSED(access))
|
||||
static int m_block_open(devminor_t minor, int UNUSED(access))
|
||||
{
|
||||
/* Open a memory block device. */
|
||||
if (m_block_part(minor) == NULL) return(ENXIO);
|
||||
|
|
@ -501,7 +493,7 @@ static int m_block_open(dev_t minor, int UNUSED(access))
|
|||
/*===========================================================================*
|
||||
* m_block_close *
|
||||
*===========================================================================*/
|
||||
static int m_block_close(dev_t minor)
|
||||
static int m_block_close(devminor_t minor)
|
||||
{
|
||||
/* Close a memory block device. */
|
||||
if (m_block_part(minor) == NULL) return(ENXIO);
|
||||
|
|
@ -518,8 +510,8 @@ static int m_block_close(dev_t minor)
|
|||
/*===========================================================================*
|
||||
* m_block_ioctl *
|
||||
*===========================================================================*/
|
||||
static int m_block_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||
cp_grant_id_t grant)
|
||||
static int m_block_ioctl(devminor_t minor, unsigned long request,
|
||||
endpoint_t endpt, cp_grant_id_t grant, endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
/* I/O controls for the block devices of the memory driver. Currently there is
|
||||
* one I/O control specific to the memory driver:
|
||||
|
|
@ -554,7 +546,7 @@ static int m_block_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
|||
return s;
|
||||
if(is_imgrd)
|
||||
ramdev_size = 0;
|
||||
if(m_vaddrs[minor] && !cmp64(dv->dv_size, ((u64_t)(ramdev_size)))) {
|
||||
if(m_vaddrs[minor] && dv->dv_size == (u64_t) ramdev_size) {
|
||||
return(OK);
|
||||
}
|
||||
/* openct is 1 for the ioctl(). */
|
||||
|
|
@ -602,7 +594,7 @@ static int m_block_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
|||
|
||||
m_vaddrs[minor] = (vir_bytes) mem;
|
||||
|
||||
dv->dv_size = ((u64_t)(ramdev_size));
|
||||
dv->dv_size = ramdev_size;
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ static struct log log = {
|
|||
/* holding the current host controller */
|
||||
static struct mmc_host host;
|
||||
|
||||
#define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS)
|
||||
#define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE)
|
||||
|
||||
/* When passing data over a grant one needs to pass
|
||||
|
|
@ -40,19 +39,19 @@ static struct mmc_host host;
|
|||
#define COPYBUFF_SIZE 0x1000 /* 4k buff */
|
||||
static unsigned char copybuff[COPYBUFF_SIZE];
|
||||
|
||||
static struct sd_slot *get_slot(dev_t minor);
|
||||
static struct sd_slot *get_slot(devminor_t minor);
|
||||
|
||||
/* Prototypes for the block device */
|
||||
static int block_open(dev_t minor, int access);
|
||||
static int block_close(dev_t minor);
|
||||
static int block_transfer(dev_t minor,
|
||||
static int block_open(devminor_t minor, int access);
|
||||
static int block_close(devminor_t minor);
|
||||
static int block_transfer(devminor_t minor,
|
||||
int do_write,
|
||||
u64_t position,
|
||||
endpoint_t endpt, iovec_t * iov, unsigned int nr_req, int flags);
|
||||
|
||||
static int block_ioctl(dev_t minor,
|
||||
unsigned int request, endpoint_t endpt, cp_grant_id_t grant);
|
||||
static struct device *block_part(dev_t minor);
|
||||
static int block_ioctl(devminor_t minor, unsigned long request,
|
||||
endpoint_t endpt, cp_grant_id_t grant, endpoint_t user_endpt);
|
||||
static struct device *block_part(devminor_t minor);
|
||||
|
||||
/* System even handling */
|
||||
static void sef_local_startup();
|
||||
|
|
@ -73,18 +72,14 @@ static void set_log_level(int level);
|
|||
|
||||
/* Entry points for the BLOCK driver. */
|
||||
static struct blockdriver mmc_driver = {
|
||||
BLOCKDRIVER_TYPE_DISK, /* handle partition requests */
|
||||
block_open, /* open or mount */
|
||||
block_close, /* on a close */
|
||||
block_transfer, /* does the I/O */
|
||||
block_ioctl, /* ioclt's */
|
||||
NULL, /* no need to clean up (yet) */
|
||||
block_part, /* return partition information */
|
||||
NULL, /* no geometry */
|
||||
hw_intr, /* left over interrupts */
|
||||
bdr_alarm, /* no alarm processing */
|
||||
NULL, /* no processing of other messages */
|
||||
NULL /* no threading support */
|
||||
.bdr_type = BLOCKDRIVER_TYPE_DISK,/* handle partition requests */
|
||||
.bdr_open = block_open, /* device open */
|
||||
.bdr_close = block_close, /* on a close */
|
||||
.bdr_transfer = block_transfer, /* does the I/O */
|
||||
.bdr_ioctl = block_ioctl, /* ioctls */
|
||||
.bdr_part = block_part, /* get partition information */
|
||||
.bdr_intr = hw_intr, /* left over interrupts */
|
||||
.bdr_alarm = bdr_alarm /* no alarm processing */
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -142,7 +137,7 @@ apply_env()
|
|||
* block_open *
|
||||
*===========================================================================*/
|
||||
static int
|
||||
block_open(dev_t minor, int access)
|
||||
block_open(devminor_t minor, int access)
|
||||
{
|
||||
struct sd_slot *slot;
|
||||
slot = get_slot(minor);
|
||||
|
|
@ -214,7 +209,7 @@ block_open(dev_t minor, int access)
|
|||
* block_close *
|
||||
*===========================================================================*/
|
||||
static int
|
||||
block_close(dev_t minor)
|
||||
block_close(devminor_t minor)
|
||||
{
|
||||
struct sd_slot *slot;
|
||||
|
||||
|
|
@ -281,7 +276,8 @@ copyfrom(endpoint_t src_e,
|
|||
* block_transfer *
|
||||
*===========================================================================*/
|
||||
static int
|
||||
block_transfer(dev_t minor, /* minor device number */
|
||||
block_transfer(
|
||||
devminor_t minor, /* minor device number */
|
||||
int do_write, /* read or write? */
|
||||
u64_t position, /* offset on device to read or write */
|
||||
endpoint_t endpt, /* process doing the request */
|
||||
|
|
@ -439,8 +435,8 @@ block_transfer(dev_t minor, /* minor device number */
|
|||
* block_ioctl *
|
||||
*===========================================================================*/
|
||||
static int
|
||||
block_ioctl(dev_t minor,
|
||||
unsigned int request, endpoint_t endpt, cp_grant_id_t grant)
|
||||
block_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
|
||||
cp_grant_id_t grant, endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
/* IOCTL handling */
|
||||
struct sd_slot *slot;
|
||||
|
|
@ -470,14 +466,14 @@ block_ioctl(dev_t minor,
|
|||
return OK;
|
||||
}
|
||||
|
||||
return EINVAL;
|
||||
return ENOTTY;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* block_part *
|
||||
*===========================================================================*/
|
||||
static struct device *
|
||||
block_part(dev_t minor)
|
||||
block_part(devminor_t minor)
|
||||
{
|
||||
/*
|
||||
* Reuse the existing MINIX major/minor partitioning scheme.
|
||||
|
|
@ -615,7 +611,7 @@ block_signal_handler_cb(int signo)
|
|||
#define IS_MINIX_SUB_PARTITION_MINOR(minor) (minor >= MINOR_d0p0s0 )
|
||||
|
||||
static struct sd_slot *
|
||||
get_slot(dev_t minor)
|
||||
get_slot(devminor_t minor)
|
||||
{
|
||||
/*
|
||||
* Get an sd_slot based on the minor number.
|
||||
|
|
@ -627,7 +623,7 @@ get_slot(dev_t minor)
|
|||
* number 128 till 144 for sub partitions.
|
||||
*/
|
||||
/* If this is a minor for the first disk (e.g. minor 0 till 5) */
|
||||
if (minor / DEV_PER_DRIVE == 0) {
|
||||
if (minor >= 0 && minor / DEV_PER_DRIVE == 0) {
|
||||
/* we are talking about the first disk and that is all we
|
||||
* support */
|
||||
return &host.slot[0];
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
/* State management variables. */
|
||||
EXTERN int writing;
|
||||
EXTERN int is_status_msg_expected;
|
||||
|
||||
/* Custom states definition. */
|
||||
#define PR_STATE_WRITE_PROTOCOL_FREE (SEF_LU_STATE_CUSTOM_BASE + 0)
|
||||
|
|
@ -24,7 +23,7 @@ int sef_cb_lu_prepare(int state)
|
|||
break;
|
||||
|
||||
case SEF_LU_STATE_PROTOCOL_FREE:
|
||||
is_ready = (!writing && !is_status_msg_expected);
|
||||
is_ready = (!writing);
|
||||
break;
|
||||
|
||||
/* Custom states. */
|
||||
|
|
@ -52,15 +51,13 @@ void sef_cb_lu_state_dump(int state)
|
|||
{
|
||||
sef_lu_dprint("printer: live update state = %d\n", state);
|
||||
sef_lu_dprint("printer: writing = %d\n", writing);
|
||||
sef_lu_dprint("printer: is_status_msg_expected = %d\n",
|
||||
is_status_msg_expected);
|
||||
|
||||
sef_lu_dprint("printer: SEF_LU_STATE_WORK_FREE(%d) reached = %d\n",
|
||||
SEF_LU_STATE_WORK_FREE, TRUE);
|
||||
sef_lu_dprint("printer: SEF_LU_STATE_REQUEST_FREE(%d) reached = %d\n",
|
||||
SEF_LU_STATE_REQUEST_FREE, TRUE);
|
||||
sef_lu_dprint("printer: SEF_LU_STATE_PROTOCOL_FREE(%d) reached = %d\n",
|
||||
SEF_LU_STATE_PROTOCOL_FREE, (!writing && !is_status_msg_expected));
|
||||
SEF_LU_STATE_PROTOCOL_FREE, (!writing));
|
||||
sef_lu_dprint("printer: PR_STATE_WRITE_PROTOCOL_FREE(%d) reached = %d\n",
|
||||
PR_STATE_WRITE_PROTOCOL_FREE, (!writing));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,29 +5,6 @@
|
|||
* Changes:
|
||||
* May 07, 2004 fix: wait until printer is ready (Jorrit N. Herder)
|
||||
* May 06, 2004 printer driver moved to user-space (Jorrit N. Herder)
|
||||
*
|
||||
* The valid messages and their parameters are:
|
||||
*
|
||||
* DEV_OPEN: initializes the printer
|
||||
* DEV_CLOSE: does nothing
|
||||
* HARD_INT: interrupt handler has finished current chunk of output
|
||||
* DEV_WRITE: a process wants to write on a terminal
|
||||
* CANCEL: terminate a previous incomplete system call immediately
|
||||
*
|
||||
* m_type TTY_LINE USER_ENDPT COUNT ADDRESS
|
||||
* |-------------+---------+---------+---------+---------|
|
||||
* | DEV_OPEN | | | | |
|
||||
* |-------------+---------+---------+---------+---------|
|
||||
* | DEV_CLOSE | | proc nr | | |
|
||||
* -------------------------------------------------------
|
||||
* | HARD_INT | | | | |
|
||||
* |-------------+---------+---------+---------+---------|
|
||||
* | SYS_EVENT | | | | |
|
||||
* |-------------+---------+---------+---------+---------|
|
||||
* | DEV_WRITE |minor dev| proc nr | count | buf ptr |
|
||||
* |-------------+---------+---------+---------+---------|
|
||||
* | CANCEL |minor dev| proc nr | | |
|
||||
* -------------------------------------------------------
|
||||
*
|
||||
* Note: since only 1 printer is supported, minor dev is not used at present.
|
||||
*/
|
||||
|
|
@ -87,30 +64,29 @@
|
|||
*/
|
||||
|
||||
static endpoint_t caller; /* process to tell when printing done (FS) */
|
||||
static int revive_pending; /* set to true if revive is pending */
|
||||
static int revive_status; /* revive status */
|
||||
static int done_status; /* status of last output completion */
|
||||
static int oleft; /* bytes of output left in obuf */
|
||||
static unsigned char obuf[128]; /* output buffer */
|
||||
static unsigned const char *optr; /* ptr to next char in obuf to print */
|
||||
static int orig_count; /* original byte count */
|
||||
static int port_base; /* I/O port for printer */
|
||||
static endpoint_t proc_nr; /* user requesting the printing */
|
||||
static cp_grant_id_t grant_nr; /* grant on which print happens */
|
||||
static int user_left; /* bytes of output left in user buf */
|
||||
static vir_bytes user_vir_d; /* offset in user buf */
|
||||
int writing; /* nonzero while write is in progress */
|
||||
static cdev_id_t write_id; /* request ID of ongoing write */
|
||||
static int irq_hook_id; /* id of irq hook at kernel */
|
||||
|
||||
static void do_cancel(message *m_ptr);
|
||||
static void output_done(void);
|
||||
static void do_write(message *m_ptr);
|
||||
static void do_status(message *m_ptr);
|
||||
static void prepare_output(void);
|
||||
static int do_probe(void);
|
||||
static void do_initialize(void);
|
||||
static void reply(int code,int replyee,int proc,int status);
|
||||
static void do_printer_output(void);
|
||||
static int printer_open(devminor_t minor, int access, endpoint_t user_endpt);
|
||||
static ssize_t printer_write(devminor_t minor, u64_t position,
|
||||
endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
|
||||
cdev_id_t id);
|
||||
static int printer_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id);
|
||||
static void printer_intr(unsigned int mask);
|
||||
|
||||
/* SEF functions and variables. */
|
||||
static void sef_local_startup(void);
|
||||
|
|
@ -118,7 +94,14 @@ static int sef_cb_init_fresh(int type, sef_init_info_t *info);
|
|||
EXTERN int sef_cb_lu_prepare(int state);
|
||||
EXTERN int sef_cb_lu_state_isvalid(int state);
|
||||
EXTERN void sef_cb_lu_state_dump(int state);
|
||||
int is_status_msg_expected = FALSE;
|
||||
|
||||
/* Entry points to this driver. */
|
||||
static struct chardriver printer_tab = {
|
||||
.cdr_open = printer_open,
|
||||
.cdr_write = printer_write,
|
||||
.cdr_cancel = printer_cancel,
|
||||
.cdr_intr = printer_intr
|
||||
};
|
||||
|
||||
/*===========================================================================*
|
||||
* printer_task *
|
||||
|
|
@ -126,44 +109,11 @@ int is_status_msg_expected = FALSE;
|
|||
int main(void)
|
||||
{
|
||||
/* Main routine of the printer task. */
|
||||
message pr_mess; /* buffer for all incoming messages */
|
||||
int ipc_status;
|
||||
|
||||
/* SEF local startup. */
|
||||
sef_local_startup();
|
||||
|
||||
while (TRUE) {
|
||||
if(driver_receive(ANY, &pr_mess, &ipc_status) != OK) {
|
||||
panic("driver_receive failed");
|
||||
}
|
||||
|
||||
if (is_ipc_notify(ipc_status)) {
|
||||
switch (_ENDPOINT_P(pr_mess.m_source)) {
|
||||
case HARDWARE:
|
||||
do_printer_output();
|
||||
break;
|
||||
default:
|
||||
reply(TASK_REPLY, pr_mess.m_source,
|
||||
pr_mess.USER_ENDPT, EINVAL);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(pr_mess.m_type) {
|
||||
case DEV_OPEN:
|
||||
do_initialize(); /* initialize */
|
||||
/* fall through */
|
||||
case DEV_CLOSE:
|
||||
reply(TASK_REPLY, pr_mess.m_source, pr_mess.USER_ENDPT, OK);
|
||||
break;
|
||||
case DEV_WRITE_S: do_write(&pr_mess); break;
|
||||
case DEV_STATUS: do_status(&pr_mess); break;
|
||||
case CANCEL: do_cancel(&pr_mess); break;
|
||||
default:
|
||||
reply(TASK_REPLY, pr_mess.m_source, pr_mess.USER_ENDPT,
|
||||
EINVAL);
|
||||
}
|
||||
}
|
||||
chardriver_task(&printer_tab);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
@ -208,53 +158,49 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
|||
/*===========================================================================*
|
||||
* do_write *
|
||||
*===========================================================================*/
|
||||
static void do_write(m_ptr)
|
||||
register message *m_ptr; /* pointer to the newly arrived message */
|
||||
static ssize_t printer_write(devminor_t UNUSED(minor), u64_t UNUSED(position),
|
||||
endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
|
||||
cdev_id_t id)
|
||||
{
|
||||
/* The printer is used by sending DEV_WRITE messages to it. Process one. */
|
||||
/* The printer is used by sending write requests to it. Process one. */
|
||||
int retries;
|
||||
u32_t status;
|
||||
|
||||
register int r = SUSPEND;
|
||||
int retries;
|
||||
u32_t status;
|
||||
/* Reject command if last write is not yet finished, the count is not
|
||||
* positive, or we're asked not to block.
|
||||
*/
|
||||
if (writing) return EIO;
|
||||
if (size <= 0) return EINVAL;
|
||||
if (flags & CDEV_NONBLOCK) return EAGAIN; /* not supported */
|
||||
|
||||
/* Reject command if last write is not yet finished, the count is not
|
||||
* positive, or the user address is bad.
|
||||
*/
|
||||
if (writing) r = EIO;
|
||||
else if (m_ptr->COUNT <= 0) r = EINVAL;
|
||||
/* If no errors occurred, continue printing with the caller.
|
||||
* First wait until the printer is online to prevent stupid errors.
|
||||
*/
|
||||
caller = endpt;
|
||||
user_left = size;
|
||||
orig_count = size;
|
||||
user_vir_d = 0; /* Offset. */
|
||||
writing = TRUE;
|
||||
grant_nr = grant;
|
||||
write_id = id;
|
||||
|
||||
/* Reply to FS, no matter what happened, possible SUSPEND caller. */
|
||||
reply(TASK_REPLY, m_ptr->m_source, m_ptr->USER_ENDPT, r);
|
||||
|
||||
/* If no errors occurred, continue printing with SUSPENDED caller.
|
||||
* First wait until the printer is online to prevent stupid errors.
|
||||
*/
|
||||
if (SUSPEND == r) {
|
||||
caller = m_ptr->m_source;
|
||||
proc_nr = m_ptr->USER_ENDPT;
|
||||
user_left = m_ptr->COUNT;
|
||||
orig_count = m_ptr->COUNT;
|
||||
user_vir_d = 0; /* Offset. */
|
||||
writing = TRUE;
|
||||
grant_nr = (cp_grant_id_t) m_ptr->IO_GRANT;
|
||||
|
||||
retries = MAX_ONLINE_RETRIES + 1;
|
||||
while (--retries > 0) {
|
||||
if(sys_inb(port_base + 1, &status) != OK) {
|
||||
retries = MAX_ONLINE_RETRIES + 1;
|
||||
while (--retries > 0) {
|
||||
if (sys_inb(port_base + 1, &status) != OK) {
|
||||
printf("printer: sys_inb of %x failed\n", port_base+1);
|
||||
panic("sys_inb failed");
|
||||
}
|
||||
if ((status & ON_LINE)) { /* printer online! */
|
||||
prepare_output();
|
||||
do_printer_output();
|
||||
return;
|
||||
}
|
||||
micro_delay(500000); /* wait before retry */
|
||||
}
|
||||
/* If we reach this point, the printer was not online in time. */
|
||||
done_status = status;
|
||||
output_done();
|
||||
}
|
||||
}
|
||||
if (status & ON_LINE) { /* printer online! */
|
||||
prepare_output();
|
||||
printer_intr(0);
|
||||
return EDONTREPLY; /* we may already have sent a reply */
|
||||
}
|
||||
micro_delay(500000); /* wait before retry */
|
||||
}
|
||||
/* If we reach this point, the printer was not online in time. */
|
||||
done_status = status;
|
||||
output_done();
|
||||
return EDONTREPLY;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
@ -265,11 +211,11 @@ static void output_done()
|
|||
/* Previous chunk of printing is finished. Continue if OK and more.
|
||||
* Otherwise, reply to caller (FS).
|
||||
*/
|
||||
register int status;
|
||||
int status;
|
||||
|
||||
if (!writing) return; /* probably leftover interrupt */
|
||||
if (done_status != OK) { /* printer error occurred */
|
||||
status = EIO;
|
||||
if (!writing) return; /* probably leftover interrupt */
|
||||
if (done_status != OK) { /* printer error occurred */
|
||||
status = EIO;
|
||||
if ((done_status & ON_LINE) == 0) {
|
||||
printf("Printer is not on line\n");
|
||||
} else if ((done_status & NO_PAPER)) {
|
||||
|
|
@ -283,79 +229,36 @@ static void output_done()
|
|||
status = orig_count - user_left;
|
||||
}
|
||||
oleft = 0; /* cancel further output */
|
||||
}
|
||||
else if (user_left != 0) { /* not yet done, continue! */
|
||||
} else if (user_left != 0) { /* not yet done, continue! */
|
||||
prepare_output();
|
||||
return;
|
||||
}
|
||||
else { /* done! report back to FS */
|
||||
} else { /* done! report back to FS */
|
||||
status = orig_count;
|
||||
}
|
||||
is_status_msg_expected = TRUE;
|
||||
revive_pending = TRUE;
|
||||
revive_status = status;
|
||||
notify(caller);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_status *
|
||||
*===========================================================================*/
|
||||
static void do_status(m_ptr)
|
||||
register message *m_ptr; /* pointer to the newly arrived message */
|
||||
{
|
||||
if (revive_pending) {
|
||||
m_ptr->m_type = DEV_REVIVE; /* build message */
|
||||
m_ptr->REP_ENDPT = proc_nr;
|
||||
m_ptr->REP_STATUS = revive_status;
|
||||
m_ptr->REP_IO_GRANT = grant_nr;
|
||||
|
||||
writing = FALSE; /* unmark event */
|
||||
revive_pending = FALSE; /* unmark event */
|
||||
} else {
|
||||
m_ptr->m_type = DEV_NO_STATUS;
|
||||
|
||||
is_status_msg_expected = FALSE;
|
||||
}
|
||||
send(m_ptr->m_source, m_ptr); /* send the message */
|
||||
|
||||
chardriver_reply_task(caller, write_id, status);
|
||||
|
||||
writing = FALSE; /* unmark event */
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_cancel *
|
||||
* printer_cancel *
|
||||
*===========================================================================*/
|
||||
static void do_cancel(m_ptr)
|
||||
register message *m_ptr; /* pointer to the newly arrived message */
|
||||
static int printer_cancel(devminor_t UNUSED(minor), endpoint_t endpt,
|
||||
cdev_id_t id)
|
||||
{
|
||||
/* Cancel a print request that has already started. Usually this means that
|
||||
* the process doing the printing has been killed by a signal. It is not
|
||||
* clear if there are race conditions. Try not to cancel the wrong process,
|
||||
* but rely on FS to handle the EINTR reply and de-suspension properly.
|
||||
* but rely on VFS to handle the EINTR reply and de-suspension properly.
|
||||
*/
|
||||
|
||||
if (writing && m_ptr->USER_ENDPT == proc_nr) {
|
||||
if (writing && caller == endpt && write_id == id) {
|
||||
oleft = 0; /* cancel output by interrupt handler */
|
||||
writing = FALSE;
|
||||
revive_pending = FALSE;
|
||||
return EINTR;
|
||||
}
|
||||
reply(TASK_REPLY, m_ptr->m_source, m_ptr->USER_ENDPT, EINTR);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* reply *
|
||||
*===========================================================================*/
|
||||
static void reply(code, replyee, process, status)
|
||||
int code; /* TASK_REPLY or REVIVE */
|
||||
int replyee; /* destination for message (normally FS) */
|
||||
int process; /* which user requested the printing */
|
||||
int status; /* number of chars printed or error code */
|
||||
{
|
||||
/* Send a reply telling FS that printing has started or stopped. */
|
||||
|
||||
message pr_mess;
|
||||
|
||||
pr_mess.m_type = code; /* TASK_REPLY or REVIVE */
|
||||
pr_mess.REP_STATUS = status; /* count or EIO */
|
||||
pr_mess.REP_ENDPT = process; /* which user does this pertain to */
|
||||
send(replyee, &pr_mess); /* send the message */
|
||||
return EDONTREPLY;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
@ -367,7 +270,7 @@ static int do_probe(void)
|
|||
|
||||
/* Get the base port for first printer. */
|
||||
if(sys_readbios(LPT1_IO_PORT_ADDR, &port_base, LPT1_IO_PORT_SIZE) != OK) {
|
||||
panic("do_initialize: sys_readbios failed");
|
||||
panic("do_probe: sys_readbios failed");
|
||||
}
|
||||
|
||||
/* If the port is zero, the parallel port is not available at all. */
|
||||
|
|
@ -380,10 +283,6 @@ static int do_probe(void)
|
|||
static void do_initialize()
|
||||
{
|
||||
/* Set global variables and initialize the printer. */
|
||||
static int initialized = FALSE;
|
||||
if (initialized) return;
|
||||
initialized = TRUE;
|
||||
|
||||
if(sys_outb(port_base + 2, INIT_PRINTER) != OK) {
|
||||
printf("printer: sys_outb of %x failed\n", port_base+2);
|
||||
panic("do_initialize: sys_outb init failed");
|
||||
|
|
@ -400,6 +299,24 @@ static void do_initialize()
|
|||
}
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* printer_open *
|
||||
*==========================================================================*/
|
||||
static int printer_open(devminor_t UNUSED(minor), int UNUSED(access),
|
||||
endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
/* Initialize on first open. */
|
||||
static int initialized = FALSE;
|
||||
|
||||
if (!initialized) {
|
||||
do_initialize();
|
||||
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* prepare_output *
|
||||
*==========================================================================*/
|
||||
|
|
@ -424,9 +341,9 @@ static void prepare_output()
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_printer_output *
|
||||
* printer_intr *
|
||||
*===========================================================================*/
|
||||
static void do_printer_output()
|
||||
static void printer_intr(unsigned int UNUSED(mask))
|
||||
{
|
||||
/* This function does the actual output to the printer. This is called on an
|
||||
* interrupt message sent from the generic interrupt handler that 'forwards'
|
||||
|
|
|
|||
|
|
@ -21,25 +21,20 @@ static dev_t m_device; /* current device */
|
|||
extern int errno; /* error number for PM calls */
|
||||
|
||||
static struct device *r_prepare(dev_t device);
|
||||
static int r_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t *iov, unsigned int nr_req, endpoint_t user_endpt, unsigned int
|
||||
flags);
|
||||
static int r_do_open(message *m_ptr);
|
||||
static void r_random(message *m_ptr);
|
||||
static ssize_t r_read(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
static ssize_t r_write(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
static int r_open(devminor_t minor, int access, endpoint_t user_endpt);
|
||||
static void r_random(clock_t stamp);
|
||||
static void r_updatebin(int source, struct k_randomness_bin *rb);
|
||||
|
||||
/* Entry points to this driver. */
|
||||
static struct chardriver r_dtab = {
|
||||
r_do_open, /* open or mount */
|
||||
do_nop, /* nothing on a close */
|
||||
nop_ioctl, /* no I/O controls supported */
|
||||
r_prepare, /* prepare for I/O on a given minor device */
|
||||
r_transfer, /* do the I/O */
|
||||
nop_cleanup, /* no need to clean up */
|
||||
r_random, /* get randomness from kernel (alarm) */
|
||||
nop_cancel, /* cancel not supported */
|
||||
nop_select, /* select not supported */
|
||||
NULL, /* other messages not supported */
|
||||
.cdr_open = r_open, /* open device */
|
||||
.cdr_read = r_read, /* read from device */
|
||||
.cdr_write = r_write, /* write to device (seeding it) */
|
||||
.cdr_alarm = r_random /* get randomness from kernel (alarm) */
|
||||
};
|
||||
|
||||
/* Buffer for the /dev/random number generator. */
|
||||
|
|
@ -59,7 +54,7 @@ int main(void)
|
|||
sef_local_startup();
|
||||
|
||||
/* Call the generic receive loop. */
|
||||
chardriver_task(&r_dtab, CHARDRIVER_ASYNC);
|
||||
chardriver_task(&r_dtab);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
|
@ -92,7 +87,7 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
|||
int i, s;
|
||||
|
||||
random_init();
|
||||
r_random(NULL); /* also set periodic timer */
|
||||
r_random(0); /* also set periodic timer */
|
||||
|
||||
/* Retrieve first randomness buffer with parameters. */
|
||||
if (OK != (s=sys_getrandomness(&krandom))) {
|
||||
|
|
@ -120,103 +115,71 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* r_prepare *
|
||||
* r_read *
|
||||
*===========================================================================*/
|
||||
static struct device *r_prepare(dev_t device)
|
||||
static ssize_t r_read(devminor_t minor, u64_t UNUSED(position),
|
||||
endpoint_t endpt, cp_grant_id_t grant, size_t size, int UNUSED(flags),
|
||||
cdev_id_t UNUSED(id))
|
||||
{
|
||||
/* Prepare for I/O on a device: check if the minor device number is ok. */
|
||||
|
||||
if (device >= NR_DEVS) return(NULL);
|
||||
m_device = device;
|
||||
|
||||
return(&m_geom[device]);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* r_transfer *
|
||||
*===========================================================================*/
|
||||
static int r_transfer(
|
||||
endpoint_t endpt, /* endpoint of grant owner */
|
||||
int opcode, /* DEV_GATHER or DEV_SCATTER */
|
||||
u64_t position, /* offset on device to read or write */
|
||||
iovec_t *iov, /* pointer to read or write request vector */
|
||||
unsigned int nr_req, /* length of request vector */
|
||||
endpoint_t UNUSED(user_endpt),/* endpoint of user process */
|
||||
unsigned int UNUSED(flags)
|
||||
)
|
||||
{
|
||||
/* Read or write one the driver's minor devices. */
|
||||
unsigned count, left, chunk;
|
||||
cp_grant_id_t grant;
|
||||
struct device *dv;
|
||||
/* Read from one of the driver's minor devices. */
|
||||
size_t offset, chunk;
|
||||
int r;
|
||||
size_t vir_offset = 0;
|
||||
|
||||
/* Get minor device number and check for /dev/null. */
|
||||
dv = &m_geom[m_device];
|
||||
if (minor != RANDOM_DEV) return(EIO);
|
||||
|
||||
while (nr_req > 0) {
|
||||
if (!random_isseeded()) return(EAGAIN);
|
||||
|
||||
/* How much to transfer and where to / from. */
|
||||
count = iov->iov_size;
|
||||
grant = (cp_grant_id_t) iov->iov_addr;
|
||||
|
||||
switch (m_device) {
|
||||
|
||||
/* Random number generator. Character instead of block device. */
|
||||
case RANDOM_DEV:
|
||||
if (opcode == DEV_GATHER_S && !random_isseeded())
|
||||
return(EAGAIN);
|
||||
left = count;
|
||||
while (left > 0) {
|
||||
chunk = (left > RANDOM_BUF_SIZE) ? RANDOM_BUF_SIZE : left;
|
||||
if (opcode == DEV_GATHER_S) {
|
||||
random_getbytes(random_buf, chunk);
|
||||
r= sys_safecopyto(endpt, grant, vir_offset,
|
||||
(vir_bytes) random_buf, chunk);
|
||||
if (r != OK)
|
||||
{
|
||||
printf("random: sys_safecopyto failed for proc %d, "
|
||||
"grant %d\n", endpt, grant);
|
||||
return r;
|
||||
}
|
||||
} else if (opcode == DEV_SCATTER_S) {
|
||||
r= sys_safecopyfrom(endpt, grant, vir_offset,
|
||||
(vir_bytes) random_buf, chunk);
|
||||
if (r != OK)
|
||||
{
|
||||
printf("random: sys_safecopyfrom failed for proc %d, "
|
||||
"grant %d\n", endpt, grant);
|
||||
return r;
|
||||
}
|
||||
random_putbytes(random_buf, chunk);
|
||||
}
|
||||
vir_offset += chunk;
|
||||
left -= chunk;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Unknown (illegal) minor device. */
|
||||
default:
|
||||
return(EINVAL);
|
||||
for (offset = 0; offset < size; offset += chunk) {
|
||||
chunk = MIN(size - offset, RANDOM_BUF_SIZE);
|
||||
random_getbytes(random_buf, chunk);
|
||||
r = sys_safecopyto(endpt, grant, offset, (vir_bytes)random_buf, chunk);
|
||||
if (r != OK) {
|
||||
printf("random: sys_safecopyto failed for proc %d, grant %d\n",
|
||||
endpt, grant);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Book the number of bytes transferred. */
|
||||
position= add64u(position, count);
|
||||
if ((iov->iov_size -= count) == 0) { iov++; nr_req--; vir_offset = 0; }
|
||||
|
||||
}
|
||||
return(OK);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* r_do_open *
|
||||
* r_write *
|
||||
*===========================================================================*/
|
||||
static int r_do_open(message *m_ptr)
|
||||
static ssize_t r_write(devminor_t minor, u64_t UNUSED(position),
|
||||
endpoint_t endpt, cp_grant_id_t grant, size_t size, int UNUSED(flags),
|
||||
cdev_id_t UNUSED(id))
|
||||
{
|
||||
/* Write to one of the driver's minor devices. */
|
||||
size_t offset, chunk;
|
||||
int r;
|
||||
|
||||
if (minor != RANDOM_DEV) return(EIO);
|
||||
|
||||
for (offset = 0; offset < size; offset += chunk) {
|
||||
chunk = MIN(size - offset, RANDOM_BUF_SIZE);
|
||||
r = sys_safecopyfrom(endpt, grant, offset, (vir_bytes)random_buf,
|
||||
chunk);
|
||||
if (r != OK) {
|
||||
printf("random: sys_safecopyfrom failed for proc %d,"
|
||||
" grant %d\n", endpt, grant);
|
||||
return r;
|
||||
}
|
||||
random_putbytes(random_buf, chunk);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* r_open *
|
||||
*===========================================================================*/
|
||||
static int r_open(devminor_t minor, int access, endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
/* Check device number on open.
|
||||
*/
|
||||
if (r_prepare(m_ptr->DEVICE) == NULL) return(ENXIO);
|
||||
|
||||
if (minor < 0 || minor >= NR_DEVS) return(ENXIO);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
|
@ -265,7 +228,7 @@ static void r_updatebin(int source, struct k_randomness_bin *rb)
|
|||
/*===========================================================================*
|
||||
* r_random *
|
||||
*===========================================================================*/
|
||||
static void r_random(message *UNUSED(m_ptr))
|
||||
static void r_random(clock_t UNUSED(stamp))
|
||||
{
|
||||
/* Fetch random information from the kernel to update /dev/random. */
|
||||
int s;
|
||||
|
|
|
|||
|
|
@ -116,11 +116,9 @@ static uint8_t crc8(uint8_t crc, uint8_t byte);
|
|||
static int checksum(uint8_t * bytes, int nbytes, uint8_t expected_crc);
|
||||
|
||||
/* libchardriver callbacks */
|
||||
static struct device *sht21_prepare(dev_t UNUSED(dev));
|
||||
static int sht21_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t * iov, unsigned nr_req, endpoint_t UNUSED(user_endpt),
|
||||
unsigned int UNUSED(flags));
|
||||
static int sht21_other(message * m);
|
||||
static ssize_t sht21_read(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
static void sht21_other(message * m, int ipc_status);
|
||||
|
||||
/* SEF functions */
|
||||
static int sef_cb_lu_state_save(int);
|
||||
|
|
@ -130,21 +128,8 @@ static void sef_local_startup(void);
|
|||
|
||||
/* Entry points to this driver from libchardriver. */
|
||||
static struct chardriver sht21_tab = {
|
||||
.cdr_open = do_nop,
|
||||
.cdr_close = do_nop,
|
||||
.cdr_ioctl = nop_ioctl,
|
||||
.cdr_prepare = sht21_prepare,
|
||||
.cdr_transfer = sht21_transfer,
|
||||
.cdr_cleanup = nop_cleanup,
|
||||
.cdr_alarm = nop_alarm,
|
||||
.cdr_cancel = nop_cancel,
|
||||
.cdr_select = nop_select,
|
||||
.cdr_other = sht21_other
|
||||
};
|
||||
|
||||
static struct device sht21_device = {
|
||||
.dv_base = 0,
|
||||
.dv_size = 0
|
||||
.cdr_read = sht21_read,
|
||||
.cdr_other = sht21_other
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -427,17 +412,11 @@ checksum(uint8_t * bytes, int nbytes, uint8_t expected_crc)
|
|||
}
|
||||
}
|
||||
|
||||
static struct device *
|
||||
sht21_prepare(dev_t UNUSED(dev))
|
||||
{
|
||||
return &sht21_device;
|
||||
}
|
||||
|
||||
static int
|
||||
sht21_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t * iov, unsigned nr_req, endpoint_t UNUSED(user_endpt),
|
||||
unsigned int UNUSED(flags))
|
||||
static ssize_t
|
||||
sht21_read(devminor_t UNUSED(minor), u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int UNUSED(flags), cdev_id_t UNUSED(id))
|
||||
{
|
||||
u64_t dev_size;
|
||||
int bytes, r;
|
||||
|
||||
r = measure();
|
||||
|
|
@ -452,48 +431,33 @@ sht21_transfer(endpoint_t endpt, int opcode, u64_t position,
|
|||
|
||||
log_trace(&log, "%s", buffer);
|
||||
|
||||
bytes = strlen(buffer) - position < iov->iov_size ?
|
||||
strlen(buffer) - position : iov->iov_size;
|
||||
dev_size = (u64_t)strlen(buffer);
|
||||
if (position >= dev_size) return 0;
|
||||
if (position + size > dev_size)
|
||||
size = (size_t)(dev_size - position);
|
||||
|
||||
if (bytes <= 0) {
|
||||
return OK;
|
||||
}
|
||||
r = sys_safecopyto(endpt, grant, 0,
|
||||
(vir_bytes)(buffer + (size_t)position), size);
|
||||
|
||||
switch (opcode) {
|
||||
case DEV_GATHER_S:
|
||||
r = sys_safecopyto(endpt, (cp_grant_id_t) iov->iov_addr, 0,
|
||||
(vir_bytes) (buffer + position), bytes);
|
||||
iov->iov_size -= bytes;
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return r;
|
||||
return (r != OK) ? r : size;
|
||||
}
|
||||
|
||||
static int
|
||||
sht21_other(message * m)
|
||||
static void
|
||||
sht21_other(message * m, int ipc_status)
|
||||
{
|
||||
int r;
|
||||
|
||||
switch (m->m_type) {
|
||||
case NOTIFY_MESSAGE:
|
||||
if (is_ipc_notify(ipc_status)) {
|
||||
if (m->m_source == DS_PROC_NR) {
|
||||
log_debug(&log,
|
||||
"bus driver changed state, update endpoint\n");
|
||||
i2cdriver_handle_bus_update(&bus_endpoint, bus,
|
||||
address);
|
||||
}
|
||||
r = OK;
|
||||
break;
|
||||
default:
|
||||
log_warn(&log, "Invalid message type (0x%x)\n", m->m_type);
|
||||
r = EINVAL;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
return r;
|
||||
log_warn(&log, "Invalid message type (0x%x)\n", m->m_type);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -612,7 +576,7 @@ main(int argc, char *argv[])
|
|||
|
||||
sef_local_startup();
|
||||
|
||||
chardriver_task(&sht21_tab, CHARDRIVER_SYNC);
|
||||
chardriver_task(&sht21_tab);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,14 +163,14 @@ static int check_revision(void);
|
|||
static int read_edid(uint8_t * data, size_t count);
|
||||
|
||||
/* libblockdriver callbacks */
|
||||
static int tda19988_blk_open(dev_t minor, int access);
|
||||
static int tda19988_blk_close(dev_t minor);
|
||||
static ssize_t tda19988_blk_transfer(dev_t minor, int do_write, u64_t pos,
|
||||
endpoint_t endpt, iovec_t * iov, unsigned count, int flags);
|
||||
static int tda19988_blk_ioctl(dev_t minor, unsigned int request,
|
||||
endpoint_t endpt, cp_grant_id_t grant);
|
||||
static struct device *tda19988_blk_part(dev_t minor);
|
||||
static int tda19988_blk_other(message * m);
|
||||
static int tda19988_blk_open(devminor_t minor, int access);
|
||||
static int tda19988_blk_close(devminor_t minor);
|
||||
static ssize_t tda19988_blk_transfer(devminor_t minor, int do_write, u64_t pos,
|
||||
endpoint_t endpt, iovec_t * iov, unsigned int count, int flags);
|
||||
static int tda19988_blk_ioctl(devminor_t minor, unsigned long request,
|
||||
endpoint_t endpt, cp_grant_id_t grant, endpoint_t user_endpt);
|
||||
static struct device *tda19988_blk_part(devminor_t minor);
|
||||
static void tda19988_blk_other(message * m, int ipc_status);
|
||||
|
||||
/* Entry points into the device dependent code of block drivers. */
|
||||
struct blockdriver tda19988_tab = {
|
||||
|
|
@ -178,14 +178,9 @@ struct blockdriver tda19988_tab = {
|
|||
.bdr_open = tda19988_blk_open,
|
||||
.bdr_close = tda19988_blk_close,
|
||||
.bdr_transfer = tda19988_blk_transfer,
|
||||
.bdr_ioctl = tda19988_blk_ioctl, /* nop -- always returns EINVAL */
|
||||
.bdr_cleanup = NULL, /* nothing allocated -- nothing to clean up */
|
||||
.bdr_ioctl = tda19988_blk_ioctl, /* always returns ENOTTY */
|
||||
.bdr_part = tda19988_blk_part,
|
||||
.bdr_geometry = NULL, /* no geometry (cylinders, heads, sectors, etc) */
|
||||
.bdr_intr = NULL, /* i2c devices don't generate interrupts */
|
||||
.bdr_alarm = NULL, /* alarm not needed */
|
||||
.bdr_other = tda19988_blk_other, /* to recv notify events from DS */
|
||||
.bdr_device = NULL /* 1 insance per device, threads not needed */
|
||||
.bdr_other = tda19988_blk_other /* for notify events from DS */
|
||||
};
|
||||
|
||||
/* counts the number of times a device file is open */
|
||||
|
|
@ -195,7 +190,7 @@ static int openct[NR_DEVS];
|
|||
static struct device geom[NR_DEVS];
|
||||
|
||||
static int
|
||||
tda19988_blk_open(dev_t minor, int access)
|
||||
tda19988_blk_open(devminor_t minor, int access)
|
||||
{
|
||||
log_trace(&log, "tda19988_blk_open(%d,%d)\n", minor, access);
|
||||
if (tda19988_blk_part(minor) == NULL) {
|
||||
|
|
@ -208,7 +203,7 @@ tda19988_blk_open(dev_t minor, int access)
|
|||
}
|
||||
|
||||
static int
|
||||
tda19988_blk_close(dev_t minor)
|
||||
tda19988_blk_close(devminor_t minor)
|
||||
{
|
||||
log_trace(&log, "tda19988_blk_close(%d)\n", minor);
|
||||
if (tda19988_blk_part(minor) == NULL) {
|
||||
|
|
@ -225,8 +220,8 @@ tda19988_blk_close(dev_t minor)
|
|||
}
|
||||
|
||||
static ssize_t
|
||||
tda19988_blk_transfer(dev_t minor, int do_write, u64_t pos64,
|
||||
endpoint_t endpt, iovec_t * iov, unsigned nr_req, int flags)
|
||||
tda19988_blk_transfer(devminor_t minor, int do_write, u64_t pos64,
|
||||
endpoint_t endpt, iovec_t * iov, unsigned int nr_req, int flags)
|
||||
{
|
||||
unsigned count;
|
||||
struct device *dv;
|
||||
|
|
@ -319,35 +314,32 @@ tda19988_blk_transfer(dev_t minor, int do_write, u64_t pos64,
|
|||
}
|
||||
|
||||
static int
|
||||
tda19988_blk_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||
cp_grant_id_t grant)
|
||||
tda19988_blk_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
|
||||
cp_grant_id_t grant, endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
log_trace(&log, "tda19988_blk_ioctl(%d)\n", minor);
|
||||
/* no supported ioctls for this device */
|
||||
return EINVAL;
|
||||
return ENOTTY;
|
||||
}
|
||||
|
||||
static struct device *
|
||||
tda19988_blk_part(dev_t minor)
|
||||
tda19988_blk_part(devminor_t minor)
|
||||
{
|
||||
log_trace(&log, "tda19988_blk_part(%d)\n", minor);
|
||||
|
||||
if (minor >= NR_DEVS) {
|
||||
if (minor < 0 || minor >= NR_DEVS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &geom[minor];
|
||||
}
|
||||
|
||||
static int
|
||||
tda19988_blk_other(message * m)
|
||||
static void
|
||||
tda19988_blk_other(message * m, int ipc_status)
|
||||
{
|
||||
int r;
|
||||
|
||||
log_trace(&log, "tda19988_blk_other(0x%x)\n", m->m_type);
|
||||
|
||||
switch (m->m_type) {
|
||||
case NOTIFY_MESSAGE:
|
||||
if (is_ipc_notify(ipc_status)) {
|
||||
if (m->m_source == DS_PROC_NR) {
|
||||
log_debug(&log,
|
||||
"bus driver changed state, update endpoint\n");
|
||||
|
|
@ -356,15 +348,9 @@ tda19988_blk_other(message * m)
|
|||
i2cdriver_handle_bus_update(&hdmi_bus_endpoint,
|
||||
hdmi_bus, hdmi_address);
|
||||
}
|
||||
r = OK;
|
||||
break;
|
||||
default:
|
||||
} else {
|
||||
log_warn(&log, "Invalid message type (0x%x)\n", m->m_type);
|
||||
r = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -434,7 +434,6 @@ int
|
|||
main(int argc, char *argv[])
|
||||
{
|
||||
int r;
|
||||
endpoint_t user, caller;
|
||||
message m;
|
||||
int ipc_status;
|
||||
|
||||
|
|
@ -485,26 +484,8 @@ main(int argc, char *argv[])
|
|||
continue;
|
||||
}
|
||||
|
||||
caller = m.m_source;
|
||||
user = m.USER_ENDPT;
|
||||
|
||||
/*
|
||||
* Handle Message
|
||||
*
|
||||
* So far this driver only deals with notifications
|
||||
* so it always replies to non-notifications with EINVAL.
|
||||
*/
|
||||
|
||||
/* Send Reply */
|
||||
m.m_type = TASK_REPLY;
|
||||
m.REP_ENDPT = user;
|
||||
m.REP_STATUS = EINVAL;
|
||||
|
||||
r = sendnb(caller, &m);
|
||||
if (r != OK) {
|
||||
log_warn(&log, "sendnb() failed\n");
|
||||
continue;
|
||||
}
|
||||
log_warn(&log, "Ignoring message 0x%x from 0x%x\n", m.m_type,
|
||||
m.m_source);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -69,11 +69,9 @@ static int adc_read(int adc, uint8_t * val);
|
|||
static int measure_lux(uint32_t * lux);
|
||||
|
||||
/* libchardriver callbacks */
|
||||
static struct device *tsl2550_prepare(dev_t UNUSED(dev));
|
||||
static int tsl2550_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t * iov, unsigned nr_req, endpoint_t UNUSED(user_endpt),
|
||||
unsigned int UNUSED(flags));
|
||||
static int tsl2550_other(message * m);
|
||||
static ssize_t tsl2550_read(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
static void tsl2550_other(message * m, int ipc_status);
|
||||
|
||||
/* SEF functions */
|
||||
static int sef_cb_lu_state_save(int);
|
||||
|
|
@ -83,21 +81,8 @@ static void sef_local_startup(void);
|
|||
|
||||
/* Entry points to this driver from libchardriver. */
|
||||
static struct chardriver tsl2550_tab = {
|
||||
.cdr_open = do_nop,
|
||||
.cdr_close = do_nop,
|
||||
.cdr_ioctl = nop_ioctl,
|
||||
.cdr_prepare = tsl2550_prepare,
|
||||
.cdr_transfer = tsl2550_transfer,
|
||||
.cdr_cleanup = nop_cleanup,
|
||||
.cdr_alarm = nop_alarm,
|
||||
.cdr_cancel = nop_cancel,
|
||||
.cdr_select = nop_select,
|
||||
.cdr_other = tsl2550_other
|
||||
};
|
||||
|
||||
static struct device tsl2550_device = {
|
||||
.dv_base = 0,
|
||||
.dv_size = 0
|
||||
.cdr_read = tsl2550_read,
|
||||
.cdr_other = tsl2550_other
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -379,17 +364,11 @@ tsl2550_init(void)
|
|||
return OK;
|
||||
}
|
||||
|
||||
static struct device *
|
||||
tsl2550_prepare(dev_t UNUSED(dev))
|
||||
{
|
||||
return &tsl2550_device;
|
||||
}
|
||||
|
||||
static int
|
||||
tsl2550_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t * iov, unsigned nr_req, endpoint_t UNUSED(user_endpt),
|
||||
unsigned int UNUSED(flags))
|
||||
static ssize_t
|
||||
tsl2550_read(devminor_t UNUSED(minor), u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int UNUSED(flags), cdev_id_t UNUSED(id))
|
||||
{
|
||||
u64_t dev_size;
|
||||
int bytes, r;
|
||||
uint32_t lux;
|
||||
|
||||
|
|
@ -401,48 +380,33 @@ tsl2550_transfer(endpoint_t endpt, int opcode, u64_t position,
|
|||
memset(buffer, '\0', BUFFER_LEN + 1);
|
||||
snprintf(buffer, BUFFER_LEN, "%-16s: %d\n", "ILLUMINANCE", lux);
|
||||
|
||||
bytes = strlen(buffer) - position < iov->iov_size ?
|
||||
strlen(buffer) - position : iov->iov_size;
|
||||
dev_size = (u64_t)strlen(buffer);
|
||||
if (position >= dev_size) return 0;
|
||||
if (position + size > dev_size)
|
||||
size = (size_t)(dev_size - position);
|
||||
|
||||
if (bytes <= 0) {
|
||||
return OK;
|
||||
}
|
||||
r = sys_safecopyto(endpt, grant, 0,
|
||||
(vir_bytes)(buffer + (size_t)position), size);
|
||||
|
||||
switch (opcode) {
|
||||
case DEV_GATHER_S:
|
||||
r = sys_safecopyto(endpt, (cp_grant_id_t) iov->iov_addr, 0,
|
||||
(vir_bytes) (buffer + position), bytes);
|
||||
iov->iov_size -= bytes;
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return r;
|
||||
return (r != OK) ? r : size;
|
||||
}
|
||||
|
||||
static int
|
||||
tsl2550_other(message * m)
|
||||
static void
|
||||
tsl2550_other(message * m, int ipc_status)
|
||||
{
|
||||
int r;
|
||||
|
||||
switch (m->m_type) {
|
||||
case NOTIFY_MESSAGE:
|
||||
if (is_ipc_notify(ipc_status)) {
|
||||
if (m->m_source == DS_PROC_NR) {
|
||||
log_debug(&log,
|
||||
"bus driver changed state, update endpoint\n");
|
||||
i2cdriver_handle_bus_update(&bus_endpoint, bus,
|
||||
address);
|
||||
}
|
||||
r = OK;
|
||||
break;
|
||||
default:
|
||||
log_warn(&log, "Invalid message type (0x%x)\n", m->m_type);
|
||||
r = EINVAL;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
return r;
|
||||
log_warn(&log, "Invalid message type (0x%x)\n", m->m_type);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -561,7 +525,7 @@ main(int argc, char *argv[])
|
|||
|
||||
sef_local_startup();
|
||||
|
||||
chardriver_task(&tsl2550_tab, CHARDRIVER_SYNC);
|
||||
chardriver_task(&tsl2550_tab);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ PROG= tty
|
|||
|
||||
SRCS += tty.c pty.c
|
||||
|
||||
DPADD+= ${LIBSYS} ${LIBTIMERS}
|
||||
LDADD+= -lsys -ltimers
|
||||
DPADD+= ${LIBCHARDRIVER} ${LIBSYS} ${LIBTIMERS}
|
||||
LDADD+= -lchardriver -lsys -ltimers
|
||||
|
||||
MAN=
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "tty.h"
|
||||
|
||||
void
|
||||
do_video(message *m)
|
||||
do_video(message *m, int ipc_status)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ cons_stop(void)
|
|||
}
|
||||
|
||||
int
|
||||
con_loadfont(message *m)
|
||||
con_loadfont(endpoint_t endpt, cp_grant_id_t grant)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,12 +19,7 @@ do_kb_inject(message *m)
|
|||
}
|
||||
|
||||
void
|
||||
do_kbd(message *m)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
do_kbdaux(message *m)
|
||||
do_kbd(message *m, int ipc_status)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -34,13 +29,7 @@ kb_init_once(void)
|
|||
}
|
||||
|
||||
int
|
||||
kbd_status(message *m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
kbd_loadmap(message *m)
|
||||
kbd_loadmap(endpoint_t endpt, cp_grant_id_t grant)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -239,11 +239,11 @@ rs_write(register tty_t *tp, int try)
|
|||
if (tp->tty_outcaller == KERNEL) {
|
||||
/* We're trying to print on kernel's behalf */
|
||||
memcpy(rs->ohead,
|
||||
(void *) tp->tty_outgrant + tp->tty_outoffset,
|
||||
(char *) tp->tty_outgrant + tp->tty_outcum,
|
||||
count);
|
||||
} else {
|
||||
if ((r = sys_safecopyfrom(tp->tty_outcaller,
|
||||
tp->tty_outgrant, tp->tty_outoffset,
|
||||
tp->tty_outgrant, tp->tty_outcum,
|
||||
(vir_bytes) rs->ohead, count)) != OK) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -264,31 +264,21 @@ rs_write(register tty_t *tp, int try)
|
|||
rs_ostart(rs);
|
||||
if ((rs->ohead += ocount) >= bufend(rs->obuf))
|
||||
rs->ohead -= buflen(rs->obuf);
|
||||
tp->tty_outoffset += count;
|
||||
tp->tty_outcum += count;
|
||||
if ((tp->tty_outleft -= count) == 0) {
|
||||
/* Output is finished, reply to the writer. */
|
||||
if(tp->tty_outrepcode == TTY_REVIVE) {
|
||||
notify(tp->tty_outcaller);
|
||||
tp->tty_outrevived = 1;
|
||||
} else {
|
||||
tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
|
||||
tp->tty_outproc, tp->tty_outcum);
|
||||
tp->tty_outcum = 0;
|
||||
}
|
||||
chardriver_reply_task(tp->tty_outcaller, tp->tty_outid,
|
||||
tp->tty_outcum);
|
||||
tp->tty_outcum = 0;
|
||||
tp->tty_outcaller = NONE;
|
||||
}
|
||||
|
||||
}
|
||||
if (tp->tty_outleft > 0 && tp->tty_termios.c_ospeed == B0) {
|
||||
/* Oops, the line has hung up. */
|
||||
if(tp->tty_outrepcode == TTY_REVIVE) {
|
||||
notify(tp->tty_outcaller);
|
||||
tp->tty_outrevived = 1;
|
||||
} else {
|
||||
tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
|
||||
tp->tty_outproc, EIO);
|
||||
tp->tty_outleft = tp->tty_outcum = 0;
|
||||
}
|
||||
chardriver_reply_task(tp->tty_outcaller, tp->tty_outid, EIO);
|
||||
tp->tty_outleft = tp->tty_outcum = 0;
|
||||
tp->tty_outcaller = NONE;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -18,16 +18,10 @@
|
|||
|
||||
#include <minix/drivers.h>
|
||||
#include <termios.h>
|
||||
#include <assert.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/vm.h>
|
||||
#include <sys/video.h>
|
||||
#include <sys/mman.h>
|
||||
#include <minix/tty.h>
|
||||
#include <minix/callnr.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/sys_config.h>
|
||||
#include <minix/vm.h>
|
||||
#include "tty.h"
|
||||
|
||||
/* Set this to 1 if you want console output duplicated on the first
|
||||
|
|
@ -142,6 +136,18 @@ static void vid_vid_copy(int src, int dst, int count);
|
|||
static void get_6845(int reg, unsigned *val);
|
||||
#endif
|
||||
|
||||
static int video_open(devminor_t minor, int access, endpoint_t user_endpt);
|
||||
static int video_close(devminor_t minor);
|
||||
static int video_ioctl(devminor_t minor, unsigned long request,
|
||||
endpoint_t endpt, cp_grant_id_t grant, int flags,
|
||||
endpoint_t user_endpt, cdev_id_t id);
|
||||
|
||||
static struct chardriver video_tab = {
|
||||
.cdr_open = video_open,
|
||||
.cdr_close = video_close,
|
||||
.cdr_ioctl = video_ioctl
|
||||
};
|
||||
|
||||
/*===========================================================================*
|
||||
* cons_write *
|
||||
*===========================================================================*/
|
||||
|
|
@ -174,16 +180,14 @@ int try;
|
|||
if (count > sizeof(buf)) count = sizeof(buf);
|
||||
if (tp->tty_outcaller == KERNEL) {
|
||||
/* We're trying to print on kernel's behalf */
|
||||
memcpy(buf, (void *) tp->tty_outgrant + tp->tty_outoffset,
|
||||
count);
|
||||
memcpy(buf, (char *) tp->tty_outgrant + tp->tty_outcum, count);
|
||||
} else {
|
||||
if ((result = sys_safecopyfrom(tp->tty_outcaller,
|
||||
tp->tty_outgrant, tp->tty_outoffset,
|
||||
tp->tty_outgrant, tp->tty_outcum,
|
||||
(vir_bytes) buf, count)) != OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tp->tty_outoffset += count;
|
||||
tbuf = buf;
|
||||
|
||||
/* Update terminal data structure. */
|
||||
|
|
@ -215,14 +219,10 @@ int try;
|
|||
|
||||
/* Reply to the writer if all output is finished or if an error occured. */
|
||||
if (tp->tty_outleft == 0 || result != OK) {
|
||||
if(tp->tty_outrepcode == TTY_REVIVE) {
|
||||
notify(tp->tty_outcaller);
|
||||
tp->tty_outrevived = 1;
|
||||
} else {
|
||||
tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
|
||||
tp->tty_outproc, tp->tty_outcum);
|
||||
tp->tty_outcum = 0;
|
||||
}
|
||||
chardriver_reply_task(tp->tty_outcaller, tp->tty_outid,
|
||||
result != OK ? result : tp->tty_outcum);
|
||||
tp->tty_outcum = tp->tty_outleft = 0;
|
||||
tp->tty_outcaller = NONE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -811,82 +811,69 @@ static void beep()
|
|||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* video_open *
|
||||
*===========================================================================*/
|
||||
static int video_open(devminor_t minor, int UNUSED(access),
|
||||
endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
/* Should grant IOPL */
|
||||
disable_console();
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* video_close *
|
||||
*===========================================================================*/
|
||||
static int video_close(devminor_t minor)
|
||||
{
|
||||
reenable_console();
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* video_ioctl *
|
||||
*===========================================================================*/
|
||||
static int video_ioctl(devminor_t minor, unsigned long request,
|
||||
endpoint_t endpt, cp_grant_id_t grant, int flags,
|
||||
endpoint_t user_endpt, cdev_id_t id)
|
||||
{
|
||||
struct mapreqvm mapreqvm;
|
||||
int r, do_map;
|
||||
|
||||
switch (request) {
|
||||
case TIOCMAPMEM:
|
||||
case TIOCUNMAPMEM:
|
||||
do_map = (request == TIOCMAPMEM); /* else unmap */
|
||||
|
||||
if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &mapreqvm,
|
||||
sizeof(mapreqvm))) != OK)
|
||||
return r;
|
||||
|
||||
if (do_map) {
|
||||
mapreqvm.vaddr_ret = vm_map_phys(user_endpt,
|
||||
(void *) mapreqvm.phys_offset, mapreqvm.size);
|
||||
r = sys_safecopyto(endpt, grant, 0, (vir_bytes) &mapreqvm,
|
||||
sizeof(mapreqvm));
|
||||
} else {
|
||||
r = vm_unmap_phys(user_endpt, mapreqvm.vaddr, mapreqvm.size);
|
||||
}
|
||||
|
||||
return r;
|
||||
|
||||
default:
|
||||
return ENOTTY;
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_video *
|
||||
*===========================================================================*/
|
||||
void do_video(message *m)
|
||||
void do_video(message *m, int ipc_status)
|
||||
{
|
||||
int r;
|
||||
|
||||
/* Execute the requested device driver function. */
|
||||
r= EINVAL; /* just in case */
|
||||
switch (m->m_type) {
|
||||
case DEV_OPEN:
|
||||
/* Should grant IOPL */
|
||||
disable_console();
|
||||
r= OK;
|
||||
break;
|
||||
case DEV_CLOSE:
|
||||
reenable_console();
|
||||
r= OK;
|
||||
break;
|
||||
case DEV_IOCTL_S:
|
||||
switch(m->TTY_REQUEST) {
|
||||
case TIOCMAPMEM:
|
||||
case TIOCUNMAPMEM: {
|
||||
int r, do_map;
|
||||
struct mapreqvm mapreqvm;
|
||||
|
||||
do_map= (m->REQUEST == TIOCMAPMEM); /* else unmap */
|
||||
|
||||
r = sys_safecopyfrom(m->m_source,
|
||||
(cp_grant_id_t) m->IO_GRANT, 0,
|
||||
(vir_bytes) &mapreqvm, sizeof(mapreqvm));
|
||||
|
||||
if (r != OK)
|
||||
{
|
||||
printf("tty: sys_safecopyfrom failed\n");
|
||||
tty_reply(TASK_REPLY, m->m_source,
|
||||
m->USER_ENDPT, r);
|
||||
return;
|
||||
}
|
||||
|
||||
/* In safe ioctl mode, the POSITION field contains
|
||||
* the endpt number of the original requestor.
|
||||
* USER_ENDPT is always FS.
|
||||
*/
|
||||
|
||||
if(do_map) {
|
||||
mapreqvm.vaddr_ret = vm_map_phys(m->POSITION,
|
||||
(void *) mapreqvm.phys_offset, mapreqvm.size);
|
||||
if((r = sys_safecopyto(m->m_source,
|
||||
(cp_grant_id_t) m->IO_GRANT, 0,
|
||||
(vir_bytes) &mapreqvm,
|
||||
sizeof(mapreqvm))) != OK) {
|
||||
printf("tty: sys_safecopyto failed\n");
|
||||
}
|
||||
} else {
|
||||
r = vm_unmap_phys(m->POSITION,
|
||||
mapreqvm.vaddr, mapreqvm.size);
|
||||
}
|
||||
tty_reply(TASK_REPLY, m->m_source, m->USER_ENDPT, r);
|
||||
return;
|
||||
}
|
||||
}
|
||||
r= ENOTTY;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf(
|
||||
"Warning, TTY(video) got unexpected request %d from %d\n",
|
||||
m->m_type, m->m_source);
|
||||
r= EINVAL;
|
||||
}
|
||||
tty_reply(TASK_REPLY, m->m_source, m->USER_ENDPT, r);
|
||||
chardriver_process(&video_tab, m, ipc_status);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* beep_x *
|
||||
*===========================================================================*/
|
||||
|
|
@ -1139,12 +1126,11 @@ void select_console(int cons_line)
|
|||
/*===========================================================================*
|
||||
* con_loadfont *
|
||||
*===========================================================================*/
|
||||
int con_loadfont(m)
|
||||
message *m;
|
||||
int con_loadfont(endpoint_t endpt, cp_grant_id_t grant)
|
||||
{
|
||||
|
||||
/* Load a font into the EGA or VGA adapter. */
|
||||
int result;
|
||||
int r, r2;
|
||||
static struct sequence seq1[7] = {
|
||||
{ GA_SEQUENCER_INDEX, 0x00, 0x01 },
|
||||
{ GA_SEQUENCER_INDEX, 0x02, 0x04 },
|
||||
|
|
@ -1166,17 +1152,14 @@ message *m;
|
|||
|
||||
seq2[6].value= color ? 0x0E : 0x0A;
|
||||
|
||||
result = ga_program(seq1); /* bring font memory into view */
|
||||
r = ga_program(seq1); /* bring font memory into view */
|
||||
if (r != OK) return r;
|
||||
|
||||
if(sys_safecopyfrom(m->m_source, (cp_grant_id_t) m->IO_GRANT, 0,
|
||||
(vir_bytes) font_memory, GA_FONT_SIZE) != OK) {
|
||||
printf("tty: copying from %d failed\n", m->m_source);
|
||||
return EFAULT;
|
||||
}
|
||||
r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) font_memory, GA_FONT_SIZE);
|
||||
|
||||
result = ga_program(seq2); /* restore */
|
||||
r2 = ga_program(seq2); /* restore */
|
||||
|
||||
return(result);
|
||||
return(r != OK ? r : r2);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <minix/input.h>
|
||||
#include <minix/keymap.h>
|
||||
#include <minix/reboot.h>
|
||||
#include <assert.h>
|
||||
#include "tty.h"
|
||||
#include "kernel/const.h"
|
||||
#include "kernel/config.h"
|
||||
|
|
@ -122,18 +123,17 @@ static obs_t sfkey_obs[12]; /* observers for SHIFT F1-F12 */
|
|||
|
||||
static struct kbd
|
||||
{
|
||||
int minor;
|
||||
devminor_t minor;
|
||||
int nr_open;
|
||||
char buf[KBD_BUFSZ];
|
||||
int offset;
|
||||
int avail;
|
||||
int req_size;
|
||||
int req_proc;
|
||||
size_t req_size;
|
||||
cdev_id_t req_id;
|
||||
cp_grant_id_t req_grant;
|
||||
vir_bytes req_addr_offset;
|
||||
int incaller;
|
||||
int select_ops;
|
||||
int select_proc;
|
||||
endpoint_t req_caller;
|
||||
unsigned int select_ops;
|
||||
endpoint_t select_proc;
|
||||
} kbd, kbdaux;
|
||||
|
||||
/* Data that is to be sent to the keyboard. Each byte is ACKed by the
|
||||
|
|
@ -153,8 +153,6 @@ static long sticky_alt_mode = 0;
|
|||
static long debug_fkeys = 1;
|
||||
static timer_t tmr_kbd_wd;
|
||||
|
||||
static void handle_req(struct kbd *kbdp, message *m);
|
||||
static int handle_status(struct kbd *kbdp, message *m);
|
||||
static void kbc_cmd0(int cmd);
|
||||
static void kbc_cmd1(int cmd, int data);
|
||||
static int kbc_read(void);
|
||||
|
|
@ -170,278 +168,285 @@ static int kb_read(struct tty *tp, int try);
|
|||
static unsigned map_key(int scode);
|
||||
static void kbd_watchdog(timer_t *tmrp);
|
||||
|
||||
int micro_delay(u32_t usecs)
|
||||
static int kbd_open(devminor_t minor, int access, endpoint_t user_endpt);
|
||||
static int kbd_close(devminor_t minor);
|
||||
static ssize_t kbd_read(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
static ssize_t kbd_write(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
static int kbd_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
|
||||
cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id);
|
||||
static int kbd_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id);
|
||||
static int kbd_select(devminor_t minor, unsigned int ops, endpoint_t endpt);
|
||||
|
||||
static struct chardriver kbd_tab = {
|
||||
.cdr_open = kbd_open,
|
||||
.cdr_close = kbd_close,
|
||||
.cdr_read = kbd_read,
|
||||
.cdr_write = kbd_write,
|
||||
.cdr_ioctl = kbd_ioctl,
|
||||
.cdr_cancel = kbd_cancel,
|
||||
.cdr_select = kbd_select
|
||||
};
|
||||
|
||||
/*===========================================================================*
|
||||
* line2kbd *
|
||||
*===========================================================================*/
|
||||
static struct kbd *
|
||||
line2kbd(devminor_t minor)
|
||||
{
|
||||
/* TTY can't use the library micro_delay() as that calls PM. */
|
||||
tickdelay(micros_to_ticks(usecs));
|
||||
switch (minor) {
|
||||
case KBD_MINOR: return &kbd;
|
||||
case KBDAUX_MINOR: return &kbdaux;
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* kbd_open *
|
||||
*===========================================================================*/
|
||||
static int
|
||||
kbd_open(devminor_t minor, int UNUSED(access), endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
struct kbd *kbdp;
|
||||
|
||||
if ((kbdp = line2kbd(minor)) == NULL)
|
||||
return ENXIO;
|
||||
|
||||
kbdp->nr_open++;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* kbd_close *
|
||||
*===========================================================================*/
|
||||
static int
|
||||
kbd_close(devminor_t minor)
|
||||
{
|
||||
struct kbd *kbdp;
|
||||
|
||||
if ((kbdp = line2kbd(minor)) == NULL)
|
||||
return ENXIO;
|
||||
|
||||
kbdp->nr_open--;
|
||||
if (kbdp->nr_open < 0) {
|
||||
printf("TTY(kbd): open count is negative\n");
|
||||
kbdp->nr_open= 0;
|
||||
}
|
||||
if (kbdp->nr_open == 0)
|
||||
kbdp->avail= 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* kbd_read *
|
||||
*===========================================================================*/
|
||||
static ssize_t
|
||||
kbd_read(devminor_t minor, u64_t UNUSED(position), endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id)
|
||||
{
|
||||
ssize_t n, r;
|
||||
struct kbd *kbdp;
|
||||
|
||||
if ((kbdp = line2kbd(minor)) == NULL)
|
||||
return ENXIO;
|
||||
|
||||
/* We handle only one request at a time. */
|
||||
if (kbdp->req_size)
|
||||
return EIO;
|
||||
|
||||
if ((ssize_t) size <= 0)
|
||||
return EINVAL;
|
||||
|
||||
/* If no data is available, suspend the caller. */
|
||||
if (kbdp->avail == 0) {
|
||||
if (flags & CDEV_NONBLOCK)
|
||||
return EAGAIN;
|
||||
kbdp->req_size = size;
|
||||
kbdp->req_id = id;
|
||||
kbdp->req_grant = grant;
|
||||
kbdp->req_caller = endpt;
|
||||
return EDONTREPLY;
|
||||
}
|
||||
|
||||
/* Handle read request. */
|
||||
n = kbdp->avail;
|
||||
if (n > (ssize_t) size)
|
||||
n = size;
|
||||
if (kbdp->offset + n > KBD_BUFSZ)
|
||||
n = KBD_BUFSZ - kbdp->offset;
|
||||
if (n <= 0)
|
||||
panic("do_kbd(READ): bad n: %d", n);
|
||||
r = sys_safecopyto(endpt, grant, 0,
|
||||
(vir_bytes) &kbdp->buf[kbdp->offset], n);
|
||||
if (r == OK) {
|
||||
kbdp->offset = (kbdp->offset + n) % KBD_BUFSZ;
|
||||
kbdp->avail -= n;
|
||||
r = n;
|
||||
} else
|
||||
printf("TTY(kbd): copy in read kbd failed: %d\n", r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* kbd_write *
|
||||
*===========================================================================*/
|
||||
static ssize_t
|
||||
kbd_write(devminor_t minor, u64_t UNUSED(position), endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id)
|
||||
{
|
||||
struct kbd *kbdp;
|
||||
unsigned char c;
|
||||
size_t i;
|
||||
int r;
|
||||
|
||||
if ((kbdp = line2kbd(minor)) == NULL)
|
||||
return ENXIO;
|
||||
if (kbdp != &kbdaux) {
|
||||
printf("TTY(kbd): write to keyboard not implemented\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assume that output to AUX only happens during initialization and we
|
||||
* can afford to lose input. This should be fixed at a later time.
|
||||
*/
|
||||
for (i = 0; i < size; i++) {
|
||||
r = sys_safecopyfrom(endpt, grant, i, (vir_bytes) &c, 1);
|
||||
if (r != OK)
|
||||
return i ? i : r;
|
||||
kbc_cmd1(KBC_WRITE_AUX, c);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* kbd_ioctl *
|
||||
*===========================================================================*/
|
||||
static int
|
||||
kbd_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
|
||||
cp_grant_id_t grant, int flags, endpoint_t UNUSED(user_endpt),
|
||||
cdev_id_t id)
|
||||
{
|
||||
struct kbd *kbdp;
|
||||
kio_leds_t leds;
|
||||
kio_bell_t bell;
|
||||
clock_t ticks;
|
||||
unsigned char b;
|
||||
int r;
|
||||
|
||||
if ((kbdp = line2kbd(minor)) == NULL)
|
||||
return ENXIO;
|
||||
if (kbdp != &kbd)
|
||||
return ENOTTY; /* we only support ioctls on keyboards now */
|
||||
|
||||
switch (request) {
|
||||
case KIOCSLEDS:
|
||||
r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &leds,
|
||||
sizeof(leds));
|
||||
if (r != OK)
|
||||
return r;
|
||||
|
||||
b = 0;
|
||||
if (leds.kl_bits & KBD_LEDS_NUM) b |= NUM_LOCK;
|
||||
if (leds.kl_bits & KBD_LEDS_CAPS) b |= CAPS_LOCK;
|
||||
if (leds.kl_bits & KBD_LEDS_SCROLL) b |= SCROLL_LOCK;
|
||||
if (kbdout.avail == 0)
|
||||
kbdout.offset = 0;
|
||||
if (kbdout.offset + kbdout.avail + 2 > KBD_OUT_BUFSZ) {
|
||||
/* Output buffer is full. Ignore this command.
|
||||
* Reset ACK flag.
|
||||
*/
|
||||
kbdout.expect_ack = 0;
|
||||
} else {
|
||||
kbdout.buf[kbdout.offset+kbdout.avail] = LED_CODE;
|
||||
kbdout.buf[kbdout.offset+kbdout.avail+1] = b;
|
||||
kbdout.avail += 2;
|
||||
}
|
||||
if (!kbdout.expect_ack)
|
||||
kbd_send();
|
||||
|
||||
return OK;
|
||||
|
||||
case KIOCBELL:
|
||||
r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &bell,
|
||||
sizeof(bell));
|
||||
if (r != OK)
|
||||
return r;
|
||||
|
||||
ticks = bell.kb_duration.tv_usec * system_hz / 1000000;
|
||||
ticks += bell.kb_duration.tv_sec * system_hz;
|
||||
if (!ticks)
|
||||
ticks++;
|
||||
beep_x(bell.kb_pitch, ticks);
|
||||
|
||||
return OK;
|
||||
|
||||
default:
|
||||
return ENOTTY;
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* kbd_cancel *
|
||||
*===========================================================================*/
|
||||
static int
|
||||
kbd_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id)
|
||||
{
|
||||
struct kbd *kbdp;
|
||||
|
||||
if ((kbdp = line2kbd(minor)) == NULL)
|
||||
return ENXIO;
|
||||
|
||||
if (kbdp->req_size > 0 && endpt == kbdp->req_caller &&
|
||||
id == kbdp->req_id)
|
||||
return EINTR;
|
||||
|
||||
return EDONTREPLY;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* kbd_select *
|
||||
*===========================================================================*/
|
||||
static int
|
||||
kbd_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
|
||||
{
|
||||
struct kbd *kbdp;
|
||||
int watch, ready_ops;
|
||||
|
||||
if ((kbdp = line2kbd(minor)) == NULL)
|
||||
return ENXIO;
|
||||
|
||||
watch = (ops & CDEV_NOTIFY);
|
||||
ops &= (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR);
|
||||
|
||||
ready_ops = 0;
|
||||
if (kbdp->avail && (ops & CDEV_OP_RD))
|
||||
ready_ops |= CDEV_OP_RD;
|
||||
if (ops & CDEV_OP_WR)
|
||||
ready_ops |= CDEV_OP_WR; /* writes never block */
|
||||
|
||||
ops &= ~ready_ops;
|
||||
if (ops && watch) {
|
||||
kbdp->select_ops |= ops;
|
||||
kbdp->select_proc = endpt;
|
||||
}
|
||||
|
||||
return ready_ops;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_kbd *
|
||||
*===========================================================================*/
|
||||
void do_kbd(message *m)
|
||||
void
|
||||
do_kbd(message *m, int ipc_status)
|
||||
{
|
||||
handle_req(&kbd, m);
|
||||
chardriver_process(&kbd_tab, m, ipc_status);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* kbd_status *
|
||||
*===========================================================================*/
|
||||
int kbd_status(message *m)
|
||||
{
|
||||
int r;
|
||||
|
||||
r= handle_status(&kbd, m);
|
||||
if (r)
|
||||
return r;
|
||||
return handle_status(&kbdaux, m);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_kbdaux *
|
||||
*===========================================================================*/
|
||||
void do_kbdaux(message *m)
|
||||
{
|
||||
handle_req(&kbdaux, m);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* handle_req *
|
||||
*===========================================================================*/
|
||||
static void handle_req(kbdp, m)
|
||||
struct kbd *kbdp;
|
||||
message *m;
|
||||
{
|
||||
int i, n, r, ops, watch;
|
||||
unsigned char c;
|
||||
|
||||
/* Execute the requested device driver function. */
|
||||
r= EINVAL; /* just in case */
|
||||
switch (m->m_type) {
|
||||
case DEV_OPEN:
|
||||
kbdp->nr_open++;
|
||||
r= OK;
|
||||
break;
|
||||
case DEV_CLOSE:
|
||||
kbdp->nr_open--;
|
||||
if (kbdp->nr_open < 0)
|
||||
{
|
||||
printf("TTY(kbd): open count is negative\n");
|
||||
kbdp->nr_open= 0;
|
||||
}
|
||||
if (kbdp->nr_open == 0)
|
||||
kbdp->avail= 0;
|
||||
r= OK;
|
||||
break;
|
||||
case DEV_READ_S:
|
||||
if (kbdp->req_size)
|
||||
{
|
||||
/* We handle only request at a time */
|
||||
r= EIO;
|
||||
break;
|
||||
}
|
||||
if (kbdp->avail == 0)
|
||||
{
|
||||
/* Should record proc */
|
||||
kbdp->req_size= m->COUNT;
|
||||
kbdp->req_proc= m->USER_ENDPT;
|
||||
kbdp->req_grant= (cp_grant_id_t) m->IO_GRANT;
|
||||
kbdp->req_addr_offset= 0;
|
||||
kbdp->incaller= m->m_source;
|
||||
r= SUSPEND;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Handle read request */
|
||||
n= kbdp->avail;
|
||||
if (n > m->COUNT)
|
||||
n= m->COUNT;
|
||||
if (kbdp->offset + n > KBD_BUFSZ)
|
||||
n= KBD_BUFSZ-kbdp->offset;
|
||||
if (n <= 0)
|
||||
panic("do_kbd(READ): bad n: %d", n);
|
||||
r= sys_safecopyto(m->m_source, (cp_grant_id_t) m->IO_GRANT, 0,
|
||||
(vir_bytes) &kbdp->buf[kbdp->offset], n);
|
||||
if (r == OK)
|
||||
{
|
||||
kbdp->offset= (kbdp->offset+n) % KBD_BUFSZ;
|
||||
kbdp->avail -= n;
|
||||
r= n;
|
||||
} else {
|
||||
printf("copy in read kbd failed: %d\n", r);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DEV_WRITE_S:
|
||||
if (kbdp != &kbdaux)
|
||||
{
|
||||
printf("write to keyboard not implemented\n");
|
||||
r= EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Assume that output to AUX only happens during
|
||||
* initialization and we can afford to lose input. This should
|
||||
* be fixed at a later time.
|
||||
*/
|
||||
for (i= 0; i<m->COUNT; i++)
|
||||
{
|
||||
r= sys_safecopyfrom(m->m_source, (cp_grant_id_t)
|
||||
m->IO_GRANT, i, (vir_bytes) &c, 1);
|
||||
if (r != OK)
|
||||
break;
|
||||
kbc_cmd1(KBC_WRITE_AUX, c);
|
||||
}
|
||||
r= i;
|
||||
break;
|
||||
|
||||
case CANCEL:
|
||||
kbdp->req_size= 0;
|
||||
r= OK;
|
||||
break;
|
||||
case DEV_SELECT:
|
||||
ops = m->USER_ENDPT & (SEL_RD|SEL_WR|SEL_ERR);
|
||||
watch = (m->USER_ENDPT & SEL_NOTIFY) ? 1 : 0;
|
||||
|
||||
r= 0;
|
||||
if (kbdp->avail && (ops & SEL_RD))
|
||||
{
|
||||
r |= SEL_RD;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ops && watch)
|
||||
{
|
||||
kbdp->select_ops |= ops;
|
||||
kbdp->select_proc= m->m_source;
|
||||
}
|
||||
break;
|
||||
case DEV_IOCTL_S:
|
||||
if (kbdp == &kbd && m->TTY_REQUEST == KIOCSLEDS)
|
||||
{
|
||||
kio_leds_t leds;
|
||||
unsigned char b;
|
||||
|
||||
|
||||
r= sys_safecopyfrom(m->m_source, (cp_grant_id_t)
|
||||
m->IO_GRANT, 0, (vir_bytes) &leds,
|
||||
sizeof(leds));
|
||||
if (r != OK)
|
||||
break;
|
||||
b= 0;
|
||||
if (leds.kl_bits & KBD_LEDS_NUM) b |= NUM_LOCK;
|
||||
if (leds.kl_bits & KBD_LEDS_CAPS) b |= CAPS_LOCK;
|
||||
if (leds.kl_bits & KBD_LEDS_SCROLL) b |= SCROLL_LOCK;
|
||||
if (kbdout.avail == 0)
|
||||
kbdout.offset= 0;
|
||||
if (kbdout.offset + kbdout.avail + 2 > KBD_OUT_BUFSZ)
|
||||
{
|
||||
/* Output buffer is full. Ignore this command.
|
||||
* Reset ACK flag.
|
||||
*/
|
||||
kbdout.expect_ack= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
kbdout.buf[kbdout.offset+kbdout.avail]=
|
||||
LED_CODE;
|
||||
kbdout.buf[kbdout.offset+kbdout.avail+1]= b;
|
||||
kbdout.avail += 2;
|
||||
}
|
||||
if (!kbdout.expect_ack)
|
||||
kbd_send();
|
||||
r= OK;
|
||||
break;
|
||||
}
|
||||
if (kbdp == &kbd && m->TTY_REQUEST == KIOCBELL)
|
||||
{
|
||||
kio_bell_t bell;
|
||||
clock_t ticks;
|
||||
|
||||
r = sys_safecopyfrom(m->m_source, (cp_grant_id_t)
|
||||
m->IO_GRANT, 0, (vir_bytes) &bell,
|
||||
sizeof(bell));
|
||||
if (r != OK)
|
||||
break;
|
||||
|
||||
ticks= bell.kb_duration.tv_usec * system_hz / 1000000;
|
||||
ticks += bell.kb_duration.tv_sec * system_hz;
|
||||
if (!ticks)
|
||||
ticks++;
|
||||
beep_x(bell.kb_pitch, ticks);
|
||||
|
||||
r= OK;
|
||||
break;
|
||||
}
|
||||
r= ENOTTY;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Warning, TTY(kbd) got unexpected request %d from %d\n",
|
||||
m->m_type, m->m_source);
|
||||
r= EINVAL;
|
||||
}
|
||||
tty_reply(TASK_REPLY, m->m_source, m->USER_ENDPT, r);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* handle_status *
|
||||
*===========================================================================*/
|
||||
static int handle_status(kbdp, m)
|
||||
struct kbd *kbdp;
|
||||
message *m;
|
||||
{
|
||||
int n, r;
|
||||
|
||||
if (kbdp->avail && kbdp->req_size && m->m_source == kbdp->incaller &&
|
||||
kbdp->req_grant != GRANT_INVALID)
|
||||
{
|
||||
/* Handle read request */
|
||||
n= kbdp->avail;
|
||||
if (n > kbdp->req_size)
|
||||
n= kbdp->req_size;
|
||||
if (kbdp->offset + n > KBD_BUFSZ)
|
||||
n= KBD_BUFSZ-kbdp->offset;
|
||||
if (n <= 0)
|
||||
panic("kbd_status: bad n: %d", n);
|
||||
kbdp->req_size= 0;
|
||||
r= sys_safecopyto(kbdp->incaller, kbdp->req_grant, 0,
|
||||
(vir_bytes)&kbdp->buf[kbdp->offset], n);
|
||||
if (r == OK)
|
||||
{
|
||||
kbdp->offset= (kbdp->offset+n) % KBD_BUFSZ;
|
||||
kbdp->avail -= n;
|
||||
r= n;
|
||||
} else printf("copy in revive kbd failed: %d\n", r);
|
||||
|
||||
m->m_type = DEV_REVIVE;
|
||||
m->REP_ENDPT= kbdp->req_proc;
|
||||
m->REP_IO_GRANT= kbdp->req_grant;
|
||||
m->REP_STATUS= r;
|
||||
kbdp->req_grant = GRANT_INVALID;
|
||||
return 1;
|
||||
}
|
||||
if (kbdp->avail && (kbdp->select_ops & SEL_RD) &&
|
||||
m->m_source == kbdp->select_proc)
|
||||
{
|
||||
m->m_type = DEV_IO_READY;
|
||||
m->DEV_MINOR = kbdp->minor;
|
||||
m->DEV_SEL_OPS = SEL_RD;
|
||||
|
||||
kbdp->select_ops &= ~SEL_RD;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* map_key *
|
||||
*===========================================================================*/
|
||||
|
|
@ -486,7 +491,7 @@ int scode;
|
|||
void kbd_interrupt(message *UNUSED(m_ptr))
|
||||
{
|
||||
/* A keyboard interrupt has occurred. Process it. */
|
||||
int o, isaux;
|
||||
int n, r, o, isaux;
|
||||
unsigned char scode;
|
||||
struct kbd *kbdp;
|
||||
|
||||
|
|
@ -512,15 +517,38 @@ void kbd_interrupt(message *UNUSED(m_ptr))
|
|||
#endif
|
||||
return; /* Buffer is full */
|
||||
}
|
||||
o= (kbdp->offset + kbdp->avail) % KBD_BUFSZ;
|
||||
kbdp->buf[o]= scode;
|
||||
kbdp->avail++;
|
||||
if (kbdp->req_size) {
|
||||
notify(kbdp->incaller);
|
||||
}
|
||||
if (kbdp->select_ops & SEL_RD)
|
||||
notify(kbdp->select_proc);
|
||||
return;
|
||||
o= (kbdp->offset + kbdp->avail) % KBD_BUFSZ;
|
||||
kbdp->buf[o]= scode;
|
||||
kbdp->avail++;
|
||||
if (kbdp->req_size) {
|
||||
/* Reply to read request */
|
||||
n= kbdp->avail;
|
||||
if (n > kbdp->req_size)
|
||||
n= kbdp->req_size;
|
||||
if (kbdp->offset + n > KBD_BUFSZ)
|
||||
n= KBD_BUFSZ-kbdp->offset;
|
||||
if (n <= 0)
|
||||
panic("kbd_interrupt: bad n: %d", n);
|
||||
kbdp->req_size= 0;
|
||||
r= sys_safecopyto(kbdp->req_caller, kbdp->req_grant, 0,
|
||||
(vir_bytes)&kbdp->buf[kbdp->offset], n);
|
||||
if (r == OK)
|
||||
{
|
||||
kbdp->offset= (kbdp->offset+n) % KBD_BUFSZ;
|
||||
kbdp->avail -= n;
|
||||
r= n;
|
||||
} else printf("copy in revive kbd failed: %d\n", r);
|
||||
|
||||
chardriver_reply_task(kbdp->req_caller, kbdp->req_id, r);
|
||||
kbdp->req_caller = NONE;
|
||||
}
|
||||
/* Only satisfy pending select if characters weren't just read. */
|
||||
if (kbdp->avail && (kbdp->select_ops & CDEV_OP_RD)) {
|
||||
chardriver_reply_select(kbdp->select_proc, kbdp->minor,
|
||||
CDEV_OP_RD);
|
||||
kbdp->select_ops &= ~CDEV_OP_RD;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Store the scancode in memory so the task can get at it later. */
|
||||
|
|
@ -529,7 +557,7 @@ void kbd_interrupt(message *UNUSED(m_ptr))
|
|||
if (ihead == ibuf + KB_IN_BYTES) ihead = ibuf;
|
||||
icount++;
|
||||
tty_table[ccurrent].tty_events = 1;
|
||||
if (tty_table[ccurrent].tty_select_ops & SEL_RD) {
|
||||
if (tty_table[ccurrent].tty_select_ops & CDEV_OP_RD) {
|
||||
select_retry(&tty_table[ccurrent]);
|
||||
}
|
||||
}
|
||||
|
|
@ -553,7 +581,7 @@ void do_kb_inject(message *msg)
|
|||
if (injhead == injbuf + KB_IN_BYTES) injhead = injbuf;
|
||||
injcount++;
|
||||
tty_table[ccurrent].tty_events = 1;
|
||||
if (tty_table[ccurrent].tty_select_ops & SEL_RD) {
|
||||
if (tty_table[ccurrent].tty_select_ops & CDEV_OP_RD) {
|
||||
select_retry(&tty_table[ccurrent]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1055,12 +1083,10 @@ void kb_init_once(void)
|
|||
/*===========================================================================*
|
||||
* kbd_loadmap *
|
||||
*===========================================================================*/
|
||||
int kbd_loadmap(m)
|
||||
message *m;
|
||||
int kbd_loadmap(endpoint_t endpt, cp_grant_id_t grant)
|
||||
{
|
||||
/* Load a new keymap. */
|
||||
return sys_safecopyfrom(m->m_source, (cp_grant_id_t) m->IO_GRANT,
|
||||
0, (vir_bytes) keymap, (vir_bytes) sizeof(keymap));
|
||||
return sys_safecopyfrom(endpt, grant, 0, (vir_bytes) keymap, sizeof(keymap));
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
|||
|
|
@ -246,10 +246,11 @@ static int rs_write(register tty_t *tp, int try)
|
|||
/* Copy from user space to the RS232 output buffer. */
|
||||
if (tp->tty_outcaller == KERNEL) {
|
||||
/* We're trying to print on kernel's behalf */
|
||||
memcpy(rs->ohead, (void *) tp->tty_outgrant + tp->tty_outoffset, count);
|
||||
memcpy(rs->ohead, (char *) tp->tty_outgrant + tp->tty_outcum,
|
||||
count);
|
||||
} else {
|
||||
if ((r = sys_safecopyfrom(tp->tty_outcaller, tp->tty_outgrant,
|
||||
tp->tty_outoffset, (vir_bytes) rs->ohead, count)) != OK)
|
||||
tp->tty_outcum, (vir_bytes) rs->ohead, count)) != OK)
|
||||
printf("TTY: sys_safecopyfrom() failed: %d", r);
|
||||
}
|
||||
|
||||
|
|
@ -265,30 +266,20 @@ static int rs_write(register tty_t *tp, int try)
|
|||
rs_ostart(rs);
|
||||
if ((rs->ohead += ocount) >= bufend(rs->obuf))
|
||||
rs->ohead -= buflen(rs->obuf);
|
||||
tp->tty_outoffset += count;
|
||||
tp->tty_outcum += count;
|
||||
if ((tp->tty_outleft -= count) == 0) {
|
||||
/* Output is finished, reply to the writer. */
|
||||
if(tp->tty_outrepcode == TTY_REVIVE) {
|
||||
notify(tp->tty_outcaller);
|
||||
tp->tty_outrevived = 1;
|
||||
} else {
|
||||
tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
|
||||
tp->tty_outproc, tp->tty_outcum);
|
||||
tp->tty_outcum = 0;
|
||||
}
|
||||
chardriver_reply_task(tp->tty_outcaller, tp->tty_outid,
|
||||
tp->tty_outcum);
|
||||
tp->tty_outcum = 0;
|
||||
tp->tty_outcaller = NONE;
|
||||
}
|
||||
}
|
||||
if (tp->tty_outleft > 0 && tp->tty_termios.c_ospeed == B0) {
|
||||
/* Oops, the line has hung up. */
|
||||
if(tp->tty_outrepcode == TTY_REVIVE) {
|
||||
notify(tp->tty_outcaller);
|
||||
tp->tty_outrevived = 1;
|
||||
} else {
|
||||
tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
|
||||
tp->tty_outproc, EIO);
|
||||
tp->tty_outleft = tp->tty_outcum = 0;
|
||||
}
|
||||
chardriver_reply_task(tp->tty_outcaller, tp->tty_outid, EIO);
|
||||
tp->tty_outleft = tp->tty_outcum = 0;
|
||||
tp->tty_outcaller = NONE;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -9,20 +9,16 @@
|
|||
* This file takes care of copying data between the tty/pty device pairs and
|
||||
* the open/read/write/close calls on the pty devices. The TTY task takes
|
||||
* care of the input and output processing (interrupt, backspace, raw I/O,
|
||||
* etc.) using the pty_read() and pty_write() functions as the "keyboard" and
|
||||
* "screen" functions of the ttypX devices.
|
||||
* etc.) using the pty_slave_read() and pty_slave_write() functions as the
|
||||
* "keyboard" and "screen" functions of the ttypX devices.
|
||||
* Be careful when reading this code, the terms "reading" and "writing" are
|
||||
* used both for the tty and the pty end of the pseudo tty. Writes to one
|
||||
* end are to be read at the other end and vice-versa.
|
||||
* used both for the tty (slave) and the pty (master) end of the pseudo tty.
|
||||
* Writes to one end are to be read at the other end and vice-versa.
|
||||
*/
|
||||
|
||||
#include <minix/drivers.h>
|
||||
#include <assert.h>
|
||||
#include <termios.h>
|
||||
#include <signal.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/callnr.h>
|
||||
#include <sys/select.h>
|
||||
#include "tty.h"
|
||||
|
||||
#if NR_PTYS > 0
|
||||
|
|
@ -32,23 +28,19 @@ typedef struct pty {
|
|||
tty_t *tty; /* associated TTY structure */
|
||||
char state; /* flags: busy, closed, ... */
|
||||
|
||||
/* Read call on /dev/ptypX. */
|
||||
char rdsendreply; /* send a reply (instead of notify) */
|
||||
int rdcaller; /* process making the call (usually FS) */
|
||||
int rdproc; /* process that wants to read from the pty */
|
||||
cp_grant_id_t rdgrant; /* grant for readers address space */
|
||||
vir_bytes rdoffset; /* offset in above grant */
|
||||
int rdleft; /* # bytes yet to be read */
|
||||
int rdcum; /* # bytes written so far */
|
||||
/* Read call on master (/dev/ptypX). */
|
||||
endpoint_t rdcaller; /* process making the call, or NONE if none */
|
||||
cdev_id_t rdid; /* ID of suspended read request */
|
||||
cp_grant_id_t rdgrant; /* grant for reader's address space */
|
||||
size_t rdleft; /* # bytes yet to be read */
|
||||
size_t rdcum; /* # bytes written so far */
|
||||
|
||||
/* Write call to /dev/ptypX. */
|
||||
char wrsendreply; /* send a reply (instead of notify) */
|
||||
int wrcaller; /* process making the call (usually FS) */
|
||||
int wrproc; /* process that wants to write to the pty */
|
||||
cp_grant_id_t wrgrant; /* grant for writers address space */
|
||||
vir_bytes wroffset; /* offset in above grant */
|
||||
int wrleft; /* # bytes yet to be written */
|
||||
int wrcum; /* # bytes written so far */
|
||||
/* Write call to master (/dev/ptypX). */
|
||||
endpoint_t wrcaller; /* process making the call, or NONE if none*/
|
||||
cdev_id_t wrid; /* ID of suspended write request */
|
||||
cp_grant_id_t wrgrant; /* grant for writer's address space */
|
||||
size_t wrleft; /* # bytes yet to be written */
|
||||
size_t wrcum; /* # bytes written so far */
|
||||
|
||||
/* Output buffer. */
|
||||
int ocount; /* # characters in the buffer */
|
||||
|
|
@ -56,157 +48,299 @@ typedef struct pty {
|
|||
char obuf[2048]; /* buffer for bytes going to the pty reader */
|
||||
|
||||
/* select() data. */
|
||||
int select_ops, /* Which operations do we want to know about? */
|
||||
select_proc, /* Who wants to know about it? */
|
||||
select_ready_ops; /* For callback. */
|
||||
unsigned int select_ops; /* Which operations do we want to know about? */
|
||||
endpoint_t select_proc; /* Who wants to know about it? */
|
||||
} pty_t;
|
||||
|
||||
#define PTY_ACTIVE 0x01 /* pty is open/active */
|
||||
#define TTY_CLOSED 0x02 /* tty side has closed down */
|
||||
#define PTY_CLOSED 0x04 /* pty side has closed down */
|
||||
#define TTY_ACTIVE 0x01 /* tty is open/active */
|
||||
#define PTY_ACTIVE 0x02 /* pty is open/active */
|
||||
#define TTY_CLOSED 0x04 /* tty side has closed down */
|
||||
#define PTY_CLOSED 0x08 /* pty side has closed down */
|
||||
|
||||
static pty_t pty_table[NR_PTYS]; /* PTY bookkeeping */
|
||||
|
||||
static int pty_write(tty_t *tp, int try);
|
||||
static void pty_echo(tty_t *tp, int c);
|
||||
static void pty_start(pty_t *pp);
|
||||
static void pty_finish(pty_t *pp);
|
||||
static int pty_read(tty_t *tp, int try);
|
||||
static int pty_close(tty_t *tp, int try);
|
||||
static int pty_icancel(tty_t *tp, int try);
|
||||
static int pty_ocancel(tty_t *tp, int try);
|
||||
static int pty_select(tty_t *tp, message *m);
|
||||
|
||||
static int pty_master_open(devminor_t minor, int access,
|
||||
endpoint_t user_endpt);
|
||||
static int pty_master_close(devminor_t minor);
|
||||
static ssize_t pty_master_read(devminor_t minor, u64_t position,
|
||||
endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
|
||||
cdev_id_t id);
|
||||
static ssize_t pty_master_write(devminor_t minor, u64_t position,
|
||||
endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
|
||||
cdev_id_t id);
|
||||
static int pty_master_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id);
|
||||
static int pty_master_select(devminor_t minor, unsigned int ops,
|
||||
endpoint_t endpt);
|
||||
|
||||
static struct chardriver pty_master_tab = {
|
||||
.cdr_open = pty_master_open,
|
||||
.cdr_close = pty_master_close,
|
||||
.cdr_read = pty_master_read,
|
||||
.cdr_write = pty_master_write,
|
||||
.cdr_cancel = pty_master_cancel,
|
||||
.cdr_select = pty_master_select
|
||||
};
|
||||
|
||||
/*===========================================================================*
|
||||
* pty_master_open *
|
||||
*===========================================================================*/
|
||||
static int pty_master_open(devminor_t minor, int UNUSED(access),
|
||||
endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
tty_t *tp;
|
||||
pty_t *pp;
|
||||
|
||||
if ((tp = line2tty(minor)) == NULL)
|
||||
return ENXIO;
|
||||
pp = tp->tty_priv;
|
||||
|
||||
if (pp->state & PTY_ACTIVE)
|
||||
return EIO;
|
||||
|
||||
pp->state |= PTY_ACTIVE;
|
||||
pp->rdcum = 0;
|
||||
pp->wrcum = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pty_master_close *
|
||||
*===========================================================================*/
|
||||
static int pty_master_close(devminor_t minor)
|
||||
{
|
||||
tty_t *tp;
|
||||
pty_t *pp;
|
||||
|
||||
if ((tp = line2tty(minor)) == NULL)
|
||||
return ENXIO;
|
||||
pp = tp->tty_priv;
|
||||
|
||||
if ((pp->state & (TTY_ACTIVE | TTY_CLOSED)) != TTY_ACTIVE) {
|
||||
pp->state = 0;
|
||||
} else {
|
||||
pp->state |= PTY_CLOSED;
|
||||
sigchar(tp, SIGHUP, 1);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pty_master_read *
|
||||
*===========================================================================*/
|
||||
static ssize_t pty_master_read(devminor_t minor, u64_t UNUSED(position),
|
||||
endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
|
||||
cdev_id_t id)
|
||||
{
|
||||
tty_t *tp;
|
||||
pty_t *pp;
|
||||
ssize_t r;
|
||||
|
||||
if ((tp = line2tty(minor)) == NULL)
|
||||
return ENXIO;
|
||||
pp = tp->tty_priv;
|
||||
|
||||
/* Check, store information on the reader, do I/O. */
|
||||
if (pp->state & TTY_CLOSED)
|
||||
return 0; /* EOF */
|
||||
|
||||
if (pp->rdcaller != NONE || pp->rdleft != 0 || pp->rdcum != 0)
|
||||
return EIO;
|
||||
|
||||
if (size <= 0)
|
||||
return EINVAL;
|
||||
|
||||
pp->rdcaller = endpt;
|
||||
pp->rdid = id;
|
||||
pp->rdgrant = grant;
|
||||
pp->rdleft = size;
|
||||
pty_start(pp);
|
||||
|
||||
handle_events(tp);
|
||||
|
||||
if (pp->rdleft == 0) {
|
||||
pp->rdcaller = NONE;
|
||||
return EDONTREPLY; /* already done */
|
||||
}
|
||||
|
||||
if (flags & CDEV_NONBLOCK) {
|
||||
r = pp->rdcum > 0 ? pp->rdcum : EAGAIN;
|
||||
pp->rdleft = pp->rdcum = 0;
|
||||
pp->rdcaller = NONE;
|
||||
return r;
|
||||
}
|
||||
|
||||
return EDONTREPLY; /* do suspend */
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pty_master_write *
|
||||
*===========================================================================*/
|
||||
static ssize_t pty_master_write(devminor_t minor, u64_t UNUSED(position),
|
||||
endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
|
||||
cdev_id_t id)
|
||||
{
|
||||
tty_t *tp;
|
||||
pty_t *pp;
|
||||
ssize_t r;
|
||||
|
||||
if ((tp = line2tty(minor)) == NULL)
|
||||
return ENXIO;
|
||||
pp = tp->tty_priv;
|
||||
|
||||
/* Check, store information on the writer, do I/O. */
|
||||
if (pp->state & TTY_CLOSED)
|
||||
return EIO;
|
||||
|
||||
if (pp->wrcaller != NONE || pp->wrleft != 0 || pp->wrcum != 0)
|
||||
return EIO;
|
||||
|
||||
if (size <= 0)
|
||||
return EINVAL;
|
||||
|
||||
pp->wrcaller = endpt;
|
||||
pp->wrid = id;
|
||||
pp->wrgrant = grant;
|
||||
pp->wrleft = size;
|
||||
|
||||
handle_events(tp);
|
||||
|
||||
if (pp->wrleft == 0) {
|
||||
pp->wrcaller = NONE;
|
||||
return EDONTREPLY; /* already done */
|
||||
}
|
||||
|
||||
if (flags & CDEV_NONBLOCK) {
|
||||
r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
|
||||
pp->wrleft = pp->wrcum = 0;
|
||||
pp->wrcaller = NONE;
|
||||
return r;
|
||||
}
|
||||
|
||||
return EDONTREPLY; /* do suspend */
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pty_master_cancel *
|
||||
*===========================================================================*/
|
||||
static int pty_master_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id)
|
||||
{
|
||||
tty_t *tp;
|
||||
pty_t *pp;
|
||||
int r;
|
||||
|
||||
if ((tp = line2tty(minor)) == NULL)
|
||||
return ENXIO;
|
||||
pp = tp->tty_priv;
|
||||
|
||||
if (pp->rdcaller == endpt && pp->rdid == id) {
|
||||
/* Cancel a read from a PTY. */
|
||||
r = pp->rdcum > 0 ? pp->rdcum : EINTR;
|
||||
pp->rdleft = pp->rdcum = 0;
|
||||
pp->rdcaller = NONE;
|
||||
return r;
|
||||
}
|
||||
|
||||
if (pp->wrcaller == endpt && pp->wrid == id) {
|
||||
/* Cancel a write to a PTY. */
|
||||
r = pp->wrcum > 0 ? pp->wrcum : EINTR;
|
||||
pp->wrleft = pp->wrcum = 0;
|
||||
pp->wrcaller = NONE;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Request not found. */
|
||||
return EDONTREPLY;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* select_try_pty *
|
||||
*===========================================================================*/
|
||||
static int select_try_pty(tty_t *tp, int ops)
|
||||
{
|
||||
pty_t *pp = tp->tty_priv;
|
||||
int r = 0;
|
||||
|
||||
if (ops & CDEV_OP_WR) {
|
||||
/* Write won't block on error. */
|
||||
if (pp->state & TTY_CLOSED) r |= CDEV_OP_WR;
|
||||
else if (pp->wrleft != 0 || pp->wrcum != 0) r |= CDEV_OP_WR;
|
||||
else if (tp->tty_inleft > 0) r |= CDEV_OP_WR; /* There's a reader. */
|
||||
}
|
||||
|
||||
if (ops & CDEV_OP_RD) {
|
||||
/* Read won't block on error. */
|
||||
if (pp->state & TTY_CLOSED) r |= CDEV_OP_RD;
|
||||
else if (pp->rdleft != 0 || pp->rdcum != 0) r |= CDEV_OP_RD;
|
||||
else if (pp->ocount > 0) r |= CDEV_OP_RD; /* Actual data. */
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* select_retry_pty *
|
||||
*===========================================================================*/
|
||||
void select_retry_pty(tty_t *tp)
|
||||
{
|
||||
pty_t *pp = tp->tty_priv;
|
||||
devminor_t minor;
|
||||
int r;
|
||||
|
||||
/* See if the pty side of a pty is ready to return a select. */
|
||||
if (pp->select_ops && (r = select_try_pty(tp, pp->select_ops))) {
|
||||
minor = PTYPX_MINOR + (int) (pp - pty_table);
|
||||
chardriver_reply_select(pp->select_proc, minor, r);
|
||||
pp->select_ops &= ~r;
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pty_master_select *
|
||||
*===========================================================================*/
|
||||
static int pty_master_select(devminor_t minor, unsigned int ops,
|
||||
endpoint_t endpt)
|
||||
{
|
||||
tty_t *tp;
|
||||
pty_t *pp;
|
||||
int ready_ops, watch;
|
||||
|
||||
if ((tp = line2tty(minor)) == NULL)
|
||||
return ENXIO;
|
||||
pp = tp->tty_priv;
|
||||
|
||||
watch = (ops & CDEV_NOTIFY);
|
||||
ops &= (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR);
|
||||
|
||||
ready_ops = select_try_pty(tp, ops);
|
||||
|
||||
ops &= ~ready_ops;
|
||||
if (ops && watch) {
|
||||
pp->select_ops |= ops;
|
||||
pp->select_proc = endpt;
|
||||
}
|
||||
|
||||
return ready_ops;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_pty *
|
||||
*===========================================================================*/
|
||||
void do_pty(tty_t *tp, message *m_ptr)
|
||||
void do_pty(message *m_ptr, int ipc_status)
|
||||
{
|
||||
/* Perform an open/close/read/write call on a /dev/ptypX device. */
|
||||
pty_t *pp = tp->tty_priv;
|
||||
int r;
|
||||
/* Process a request for a PTY master (/dev/ptypX) device. */
|
||||
|
||||
switch (m_ptr->m_type) {
|
||||
case DEV_READ_S:
|
||||
/* Check, store information on the reader, do I/O. */
|
||||
if (pp->state & TTY_CLOSED) {
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
if (pp->rdleft != 0 || pp->rdcum != 0) {
|
||||
r = EIO;
|
||||
break;
|
||||
}
|
||||
if (m_ptr->COUNT <= 0) {
|
||||
r = EINVAL;
|
||||
break;
|
||||
}
|
||||
if (pp->rdgrant != GRANT_INVALID) {
|
||||
r = ENOBUFS;
|
||||
break;
|
||||
}
|
||||
pp->rdsendreply = TRUE;
|
||||
pp->rdcaller = m_ptr->m_source;
|
||||
pp->rdproc = m_ptr->USER_ENDPT;
|
||||
pp->rdgrant = (cp_grant_id_t) m_ptr->IO_GRANT;
|
||||
pp->rdoffset = 0;
|
||||
pp->rdleft = m_ptr->COUNT;
|
||||
pty_start(pp);
|
||||
handle_events(tp);
|
||||
if (pp->rdleft == 0) {
|
||||
pp->rdgrant = GRANT_INVALID;
|
||||
return; /* already done */
|
||||
}
|
||||
|
||||
{
|
||||
r = SUSPEND; /* do suspend */
|
||||
pp->rdsendreply = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEV_WRITE_S:
|
||||
/* Check, store information on the writer, do I/O. */
|
||||
if (pp->state & TTY_CLOSED) {
|
||||
r = EIO;
|
||||
break;
|
||||
}
|
||||
if (pp->wrleft != 0 || pp->wrcum != 0) {
|
||||
r = EIO;
|
||||
break;
|
||||
}
|
||||
if (m_ptr->COUNT <= 0) {
|
||||
r = EINVAL;
|
||||
break;
|
||||
}
|
||||
if (pp->wrgrant != GRANT_INVALID) {
|
||||
r = ENOBUFS;
|
||||
break;
|
||||
}
|
||||
pp->wrsendreply = TRUE;
|
||||
pp->wrcaller = m_ptr->m_source;
|
||||
pp->wrproc = m_ptr->USER_ENDPT;
|
||||
pp->wrgrant = (cp_grant_id_t) m_ptr->IO_GRANT;
|
||||
pp->wroffset = 0;
|
||||
pp->wrleft = m_ptr->COUNT;
|
||||
handle_events(tp);
|
||||
if (pp->wrleft == 0) {
|
||||
pp->wrgrant = GRANT_INVALID;
|
||||
return; /* already done */
|
||||
}
|
||||
|
||||
{
|
||||
pp->wrsendreply = FALSE; /* do suspend */
|
||||
r = SUSPEND;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEV_OPEN:
|
||||
r = pp->state != 0 ? EIO : OK;
|
||||
pp->state |= PTY_ACTIVE;
|
||||
pp->rdcum = 0;
|
||||
pp->wrcum = 0;
|
||||
break;
|
||||
|
||||
case DEV_CLOSE:
|
||||
r = OK;
|
||||
if (pp->state & TTY_CLOSED) {
|
||||
pp->state = 0;
|
||||
} else {
|
||||
pp->state |= PTY_CLOSED;
|
||||
sigchar(tp, SIGHUP, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case DEV_SELECT:
|
||||
r = pty_select(tp, m_ptr);
|
||||
break;
|
||||
|
||||
case CANCEL:
|
||||
r = EINTR;
|
||||
if (m_ptr->USER_ENDPT == pp->rdproc) {
|
||||
/* Cancel a read from a PTY. */
|
||||
r = pp->rdcum > 0 ? pp->rdcum : EAGAIN;
|
||||
pp->rdleft = pp->rdcum = 0;
|
||||
pp->rdgrant = GRANT_INVALID;
|
||||
}
|
||||
if (m_ptr->USER_ENDPT == pp->wrproc) {
|
||||
/* Cancel a write to a PTY. */
|
||||
r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
|
||||
pp->wrleft = pp->wrcum = 0;
|
||||
pp->wrgrant = GRANT_INVALID;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
r = EINVAL;
|
||||
}
|
||||
tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->USER_ENDPT, r);
|
||||
chardriver_process(&pty_master_tab, m_ptr, ipc_status);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pty_write *
|
||||
* pty_slave_write *
|
||||
*===========================================================================*/
|
||||
static int pty_write(tty_t *tp, int try)
|
||||
static int pty_slave_write(tty_t *tp, int try)
|
||||
{
|
||||
/* (*dev_write)() routine for PTYs. Transfer bytes from the writer on
|
||||
* /dev/ttypX to the output buffer.
|
||||
|
|
@ -214,19 +348,13 @@ static int pty_write(tty_t *tp, int try)
|
|||
pty_t *pp = tp->tty_priv;
|
||||
int count, ocount, s;
|
||||
|
||||
|
||||
/* PTY closed down? */
|
||||
if (pp->state & PTY_CLOSED) {
|
||||
if (try) return 1;
|
||||
if (tp->tty_outleft > 0) {
|
||||
if(tp->tty_outrepcode == TTY_REVIVE) {
|
||||
notify(tp->tty_outcaller);
|
||||
tp->tty_outrevived = 1;
|
||||
} else {
|
||||
tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
|
||||
tp->tty_outproc, EIO);
|
||||
tp->tty_outleft = tp->tty_outcum = 0;
|
||||
}
|
||||
chardriver_reply_task(tp->tty_outcaller, tp->tty_outid, EIO);
|
||||
tp->tty_outleft = tp->tty_outcum = 0;
|
||||
tp->tty_outcaller = NONE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -244,11 +372,11 @@ static int pty_write(tty_t *tp, int try)
|
|||
/* Copy from user space to the PTY output buffer. */
|
||||
if (tp->tty_outcaller == KERNEL) {
|
||||
/* We're trying to print on kernel's behalf */
|
||||
memcpy(pp->ohead, (void *) tp->tty_outgrant + tp->tty_outoffset,
|
||||
memcpy(pp->ohead, (void *) tp->tty_outgrant + tp->tty_outcum,
|
||||
count);
|
||||
} else {
|
||||
if ((s = sys_safecopyfrom(tp->tty_outcaller, tp->tty_outgrant,
|
||||
tp->tty_outoffset, (vir_bytes) pp->ohead,
|
||||
tp->tty_outcum, (vir_bytes) pp->ohead,
|
||||
count)) != OK) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -267,19 +395,13 @@ static int pty_write(tty_t *tp, int try)
|
|||
pp->ohead -= buflen(pp->obuf);
|
||||
pty_start(pp);
|
||||
|
||||
tp->tty_outoffset += count;
|
||||
|
||||
tp->tty_outcum += count;
|
||||
if ((tp->tty_outleft -= count) == 0) {
|
||||
/* Output is finished, reply to the writer. */
|
||||
if(tp->tty_outrepcode == TTY_REVIVE) {
|
||||
notify(tp->tty_outcaller);
|
||||
tp->tty_outrevived = 1;
|
||||
} else {
|
||||
tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
|
||||
tp->tty_outproc, tp->tty_outcum);
|
||||
tp->tty_outcum = 0;
|
||||
}
|
||||
chardriver_reply_task(tp->tty_outcaller, tp->tty_outid,
|
||||
tp->tty_outcum);
|
||||
tp->tty_outcum = 0;
|
||||
tp->tty_outcaller = NONE;
|
||||
}
|
||||
}
|
||||
pty_finish(pp);
|
||||
|
|
@ -287,9 +409,9 @@ static int pty_write(tty_t *tp, int try)
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pty_echo *
|
||||
* pty_slave_echo *
|
||||
*===========================================================================*/
|
||||
static void pty_echo(tty_t *tp, int c)
|
||||
static void pty_slave_echo(tty_t *tp, int c)
|
||||
{
|
||||
/* Echo one character. (Like pty_write, but only one character, optionally.) */
|
||||
|
||||
|
|
@ -326,11 +448,10 @@ static void pty_start(pty_t *pp)
|
|||
if (count == 0) break;
|
||||
|
||||
/* Copy from the output buffer to the readers address space. */
|
||||
if((s = sys_safecopyto(pp->rdcaller, pp->rdgrant,
|
||||
pp->rdoffset, (vir_bytes) pp->otail, count)) != OK) {
|
||||
if((s = sys_safecopyto(pp->rdcaller, pp->rdgrant, pp->rdcum,
|
||||
(vir_bytes) pp->otail, count)) != OK) {
|
||||
break;
|
||||
}
|
||||
pp->rdoffset += count;
|
||||
|
||||
/* Bookkeeping. */
|
||||
pp->ocount -= count;
|
||||
|
|
@ -348,21 +469,18 @@ static void pty_finish(pty_t *pp)
|
|||
/* Finish the read request of a PTY reader if there is at least one byte
|
||||
* transferred.
|
||||
*/
|
||||
if (pp->rdcum > 0) {
|
||||
if (pp->rdsendreply) {
|
||||
tty_reply(TASK_REPLY, pp->rdcaller, pp->rdproc, pp->rdcum);
|
||||
pp->rdleft = pp->rdcum = 0;
|
||||
}
|
||||
else
|
||||
notify(pp->rdcaller);
|
||||
}
|
||||
|
||||
if (pp->rdcum > 0) {
|
||||
chardriver_reply_task(pp->rdcaller, pp->rdid, pp->rdcum);
|
||||
pp->rdleft = pp->rdcum = 0;
|
||||
pp->rdcaller = NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pty_read *
|
||||
* pty_slave_read *
|
||||
*===========================================================================*/
|
||||
static int pty_read(tty_t *tp, int try)
|
||||
static int pty_slave_read(tty_t *tp, int try)
|
||||
{
|
||||
/* Offer bytes from the PTY writer for input on the TTY. (Do it one byte at
|
||||
* a time, 99% of the writes will be for one byte, so no sense in being smart.)
|
||||
|
|
@ -373,14 +491,10 @@ static int pty_read(tty_t *tp, int try)
|
|||
if (pp->state & PTY_CLOSED) {
|
||||
if (try) return 1;
|
||||
if (tp->tty_inleft > 0) {
|
||||
if(tp->tty_inrepcode == TTY_REVIVE) {
|
||||
notify(tp->tty_incaller);
|
||||
tp->tty_inrevived = 1;
|
||||
} else {
|
||||
tty_reply(tp->tty_inrepcode, tp->tty_incaller,
|
||||
tp->tty_inproc, tp->tty_incum);
|
||||
tp->tty_inleft = tp->tty_incum = 0;
|
||||
}
|
||||
chardriver_reply_task(tp->tty_incaller, tp->tty_inid,
|
||||
tp->tty_incum);
|
||||
tp->tty_inleft = tp->tty_incum = 0;
|
||||
tp->tty_incaller = NONE;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -395,12 +509,11 @@ static int pty_read(tty_t *tp, int try)
|
|||
int s;
|
||||
|
||||
/* Transfer one character to 'c'. */
|
||||
if ((s = sys_safecopyfrom(pp->wrcaller, pp->wrgrant, pp->wroffset,
|
||||
if ((s = sys_safecopyfrom(pp->wrcaller, pp->wrgrant, pp->wrcum,
|
||||
(vir_bytes) &c, 1)) != OK) {
|
||||
printf("pty: safecopy failed (error %d)\n", s);
|
||||
break;
|
||||
}
|
||||
pp->wroffset++;
|
||||
|
||||
/* Input processing. */
|
||||
if (in_process(tp, &c, 1, -1) == 0) break;
|
||||
|
|
@ -408,13 +521,9 @@ static int pty_read(tty_t *tp, int try)
|
|||
/* PTY writer bookkeeping. */
|
||||
pp->wrcum++;
|
||||
if (--pp->wrleft == 0) {
|
||||
if (pp->wrsendreply) {
|
||||
tty_reply(TASK_REPLY, pp->wrcaller, pp->wrproc,
|
||||
pp->wrcum);
|
||||
pp->wrcum = 0;
|
||||
}
|
||||
else
|
||||
notify(pp->wrcaller);
|
||||
chardriver_reply_task(pp->wrcaller, pp->wrid, pp->wrcum);
|
||||
pp->wrcum = 0;
|
||||
pp->wrcaller = NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -422,9 +531,27 @@ static int pty_read(tty_t *tp, int try)
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pty_close *
|
||||
* pty_slave_open *
|
||||
*===========================================================================*/
|
||||
static int pty_close(tty_t *tp, int UNUSED(try))
|
||||
static int pty_slave_open(tty_t *tp, int UNUSED(try))
|
||||
{
|
||||
/* The tty side has been opened. */
|
||||
pty_t *pp = tp->tty_priv;
|
||||
|
||||
/* TTY_ACTIVE may already be set, which would indicate that the slave is
|
||||
* reopened after being fully closed while the master is still open. In that
|
||||
* case TTY_CLOSED will also be set, so clear that one.
|
||||
*/
|
||||
pp->state |= TTY_ACTIVE;
|
||||
pp->state &= ~TTY_CLOSED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pty_slave_close *
|
||||
*===========================================================================*/
|
||||
static int pty_slave_close(tty_t *tp, int UNUSED(try))
|
||||
{
|
||||
/* The tty side has closed, so shut down the pty side. */
|
||||
pty_t *pp = tp->tty_priv;
|
||||
|
|
@ -432,41 +559,44 @@ static int pty_close(tty_t *tp, int UNUSED(try))
|
|||
if (!(pp->state & PTY_ACTIVE)) return 0;
|
||||
|
||||
if (pp->rdleft > 0) {
|
||||
assert(!pp->rdsendreply);
|
||||
notify(pp->rdcaller);
|
||||
chardriver_reply_task(pp->rdcaller, pp->rdid, pp->rdcum);
|
||||
pp->rdleft = pp->rdcum = 0;
|
||||
pp->rdcaller = NONE;
|
||||
}
|
||||
|
||||
if (pp->wrleft > 0) {
|
||||
assert(!pp->wrsendreply);
|
||||
notify(pp->wrcaller);
|
||||
chardriver_reply_task(pp->wrcaller, pp->wrid, pp->wrcum);
|
||||
pp->wrleft = pp->wrcum = 0;
|
||||
pp->wrcaller = NONE;
|
||||
}
|
||||
|
||||
if (pp->state & PTY_CLOSED) pp->state = 0; else pp->state |= TTY_CLOSED;
|
||||
if (pp->state & PTY_CLOSED) pp->state = 0;
|
||||
else pp->state |= TTY_CLOSED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pty_icancel *
|
||||
* pty_slave_icancel *
|
||||
*===========================================================================*/
|
||||
static int pty_icancel(tty_t *tp, int UNUSED(try))
|
||||
static int pty_slave_icancel(tty_t *tp, int UNUSED(try))
|
||||
{
|
||||
/* Discard waiting input. */
|
||||
pty_t *pp = tp->tty_priv;
|
||||
|
||||
if (pp->wrleft > 0) {
|
||||
pp->wrcum += pp->wrleft;
|
||||
pp->wrleft= 0;
|
||||
notify(pp->wrcaller);
|
||||
chardriver_reply_task(pp->wrcaller, pp->wrid, pp->wrcum + pp->wrleft);
|
||||
pp->wrcum = pp->wrleft = 0;
|
||||
pp->wrcaller = NONE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pty_ocancel *
|
||||
* pty_slave_ocancel *
|
||||
*===========================================================================*/
|
||||
static int pty_ocancel(tty_t *tp, int UNUSED(try))
|
||||
static int pty_slave_ocancel(tty_t *tp, int UNUSED(try))
|
||||
{
|
||||
/* Drain the output buffer. */
|
||||
pty_t *pp = tp->tty_priv;
|
||||
|
|
@ -490,136 +620,21 @@ void pty_init(tty_t *tp)
|
|||
pp = tp->tty_priv = &pty_table[line];
|
||||
pp->tty = tp;
|
||||
pp->select_ops = 0;
|
||||
pp->rdgrant = GRANT_INVALID;
|
||||
pp->wrgrant = GRANT_INVALID;
|
||||
pp->rdcaller = NONE;
|
||||
pp->wrcaller = NONE;
|
||||
|
||||
/* Set up output queue. */
|
||||
pp->ohead = pp->otail = pp->obuf;
|
||||
|
||||
/* Fill in TTY function hooks. */
|
||||
tp->tty_devread = pty_read;
|
||||
tp->tty_devwrite = pty_write;
|
||||
tp->tty_echo = pty_echo;
|
||||
tp->tty_icancel = pty_icancel;
|
||||
tp->tty_ocancel = pty_ocancel;
|
||||
tp->tty_close = pty_close;
|
||||
tp->tty_devread = pty_slave_read;
|
||||
tp->tty_devwrite = pty_slave_write;
|
||||
tp->tty_echo = pty_slave_echo;
|
||||
tp->tty_icancel = pty_slave_icancel;
|
||||
tp->tty_ocancel = pty_slave_ocancel;
|
||||
tp->tty_open = pty_slave_open;
|
||||
tp->tty_close = pty_slave_close;
|
||||
tp->tty_select_ops = 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pty_status *
|
||||
*===========================================================================*/
|
||||
int pty_status(message *m_ptr)
|
||||
{
|
||||
int i, event_found;
|
||||
pty_t *pp;
|
||||
|
||||
event_found = 0;
|
||||
for (i= 0, pp = pty_table; i<NR_PTYS; i++, pp++) {
|
||||
if ((((pp->state & TTY_CLOSED) && pp->rdleft > 0) ||
|
||||
pp->rdcum > 0) &&
|
||||
pp->rdcaller == m_ptr->m_source)
|
||||
{
|
||||
m_ptr->m_type = DEV_REVIVE;
|
||||
m_ptr->REP_ENDPT = pp->rdproc;
|
||||
m_ptr->REP_IO_GRANT = pp->rdgrant;
|
||||
m_ptr->REP_STATUS = pp->rdcum;
|
||||
pp->rdleft = pp->rdcum = 0;
|
||||
pp->rdgrant = GRANT_INVALID;
|
||||
event_found = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((((pp->state & TTY_CLOSED) && pp->wrleft > 0) ||
|
||||
pp->wrcum > 0) &&
|
||||
pp->wrcaller == m_ptr->m_source)
|
||||
{
|
||||
m_ptr->m_type = DEV_REVIVE;
|
||||
m_ptr->REP_ENDPT = pp->wrproc;
|
||||
m_ptr->REP_IO_GRANT = pp->wrgrant;
|
||||
if (pp->wrcum == 0)
|
||||
m_ptr->REP_STATUS = EIO;
|
||||
else
|
||||
m_ptr->REP_STATUS = pp->wrcum;
|
||||
|
||||
pp->wrleft = pp->wrcum = 0;
|
||||
pp->wrgrant = GRANT_INVALID;
|
||||
event_found = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pp->select_ready_ops && pp->select_proc == m_ptr->m_source) {
|
||||
m_ptr->m_type = DEV_IO_READY;
|
||||
m_ptr->DEV_MINOR = PTYPX_MINOR + i;
|
||||
m_ptr->DEV_SEL_OPS = pp->select_ready_ops;
|
||||
pp->select_ready_ops = 0;
|
||||
event_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return event_found;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* select_try_pty *
|
||||
*===========================================================================*/
|
||||
static int select_try_pty(tty_t *tp, int ops)
|
||||
{
|
||||
pty_t *pp = tp->tty_priv;
|
||||
int r = 0;
|
||||
|
||||
if (ops & SEL_WR) {
|
||||
/* Write won't block on error. */
|
||||
if (pp->state & TTY_CLOSED) r |= SEL_WR;
|
||||
else if (pp->wrleft != 0 || pp->wrcum != 0) r |= SEL_WR;
|
||||
else r |= SEL_WR;
|
||||
}
|
||||
|
||||
if (ops & SEL_RD) {
|
||||
/* Read won't block on error. */
|
||||
if (pp->state & TTY_CLOSED) r |= SEL_RD;
|
||||
else if (pp->rdleft != 0 || pp->rdcum != 0) r |= SEL_RD;
|
||||
else if (pp->ocount > 0) r |= SEL_RD; /* Actual data. */
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* select_retry_pty *
|
||||
*===========================================================================*/
|
||||
void select_retry_pty(tty_t *tp)
|
||||
{
|
||||
pty_t *pp = tp->tty_priv;
|
||||
int r;
|
||||
|
||||
/* See if the pty side of a pty is ready to return a select. */
|
||||
if (pp->select_ops && (r=select_try_pty(tp, pp->select_ops))) {
|
||||
pp->select_ops &= ~r;
|
||||
pp->select_ready_ops |= r;
|
||||
notify(pp->select_proc);
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pty_select *
|
||||
*===========================================================================*/
|
||||
static int pty_select(tty_t *tp, message *m)
|
||||
{
|
||||
pty_t *pp = tp->tty_priv;
|
||||
int ops, ready_ops = 0, watch;
|
||||
|
||||
ops = m->USER_ENDPT & (SEL_RD|SEL_WR|SEL_ERR);
|
||||
watch = (m->USER_ENDPT & SEL_NOTIFY) ? 1 : 0;
|
||||
|
||||
ready_ops = select_try_pty(tp, ops);
|
||||
|
||||
if (!ready_ops && ops && watch) {
|
||||
pp->select_ops |= ops;
|
||||
pp->select_proc = m->m_source;
|
||||
}
|
||||
|
||||
return ready_ops;
|
||||
}
|
||||
|
||||
#endif /* NR_PTYS > 0 */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,12 +1,11 @@
|
|||
/* tty.h - Terminals */
|
||||
|
||||
#include <minix/chardriver.h>
|
||||
#include <timers.h>
|
||||
|
||||
#undef lock
|
||||
#undef unlock
|
||||
|
||||
#define TTY_REVIVE 6767
|
||||
|
||||
/* First minor numbers for the various classes of TTY devices. */
|
||||
#define CONS_MINOR 0
|
||||
#define LOG_MINOR 15
|
||||
|
|
@ -26,9 +25,6 @@
|
|||
|
||||
#define ESC '\33' /* escape */
|
||||
|
||||
#define O_NOCTTY 00400 /* from <fcntl.h>, or cc will choke */
|
||||
#define O_NONBLOCK 04000
|
||||
|
||||
struct tty;
|
||||
typedef int(*devfun_t) (struct tty *tp, int try_only);
|
||||
typedef void(*devfunarg_t) (struct tty *tp, int c);
|
||||
|
|
@ -36,7 +32,7 @@ typedef void(*devfunarg_t) (struct tty *tp, int c);
|
|||
typedef struct tty {
|
||||
int tty_events; /* set when TTY should inspect this line */
|
||||
int tty_index; /* index into TTY table */
|
||||
int tty_minor; /* device minor number */
|
||||
devminor_t tty_minor; /* device minor number */
|
||||
|
||||
/* Input queue. Typed characters are stored here until read by a program. */
|
||||
u16_t *tty_inhead; /* pointer to place where next char goes */
|
||||
|
|
@ -63,27 +59,19 @@ typedef struct tty {
|
|||
char tty_openct; /* count of number of opens of this tty */
|
||||
|
||||
/* Information about incomplete I/O requests is stored here. */
|
||||
int tty_inrepcode; /* reply code, TASK_REPLY or REVIVE */
|
||||
char tty_inrevived; /* set to 1 if revive callback is pending */
|
||||
endpoint_t tty_incaller; /* process that made the call (usually VFS) */
|
||||
endpoint_t tty_inproc; /* process that wants to read from tty */
|
||||
endpoint_t tty_incaller; /* process that made the call, or NONE */
|
||||
cdev_id_t tty_inid; /* ID of suspended read request */
|
||||
cp_grant_id_t tty_ingrant; /* grant where data is to go */
|
||||
vir_bytes tty_inoffset; /* offset into grant */
|
||||
int tty_inleft; /* how many chars are still needed */
|
||||
int tty_incum; /* # chars input so far */
|
||||
int tty_outrepcode; /* reply code, TASK_REPLY or REVIVE */
|
||||
int tty_outrevived; /* set to 1 if revive callback is pending */
|
||||
endpoint_t tty_outcaller; /* process that made the call (usually VFS) */
|
||||
endpoint_t tty_outproc; /* process that wants to write to tty */
|
||||
size_t tty_inleft; /* how many chars are still needed */
|
||||
size_t tty_incum; /* # chars input so far */
|
||||
endpoint_t tty_outcaller; /* process that made the call, or NONE */
|
||||
cdev_id_t tty_outid; /* ID of suspended write request */
|
||||
cp_grant_id_t tty_outgrant; /* grant where data comes from */
|
||||
vir_bytes tty_outoffset; /* offset into grant */
|
||||
int tty_outleft; /* # chars yet to be output */
|
||||
int tty_outcum; /* # chars output so far */
|
||||
endpoint_t tty_iocaller; /* process that made the call (usually VFS) */
|
||||
int tty_iorevived; /* set to 1 if revive callback is pending */
|
||||
endpoint_t tty_ioproc; /* process that wants to do an ioctl */
|
||||
int tty_iostatus; /* result */
|
||||
int tty_ioreq; /* ioctl request code */
|
||||
size_t tty_outleft; /* # chars yet to be output */
|
||||
size_t tty_outcum; /* # chars output so far */
|
||||
endpoint_t tty_iocaller; /* process that made the call, or NONE */
|
||||
cdev_id_t tty_ioid; /* ID of suspended ioctl request */
|
||||
unsigned int tty_ioreq; /* ioctl request code */
|
||||
cp_grant_id_t tty_iogrant; /* virtual address of ioctl buffer or grant */
|
||||
|
||||
/* select() data */
|
||||
|
|
@ -142,13 +130,11 @@ extern struct kmessages kmess;
|
|||
void handle_events(struct tty *tp);
|
||||
void sigchar(struct tty *tp, int sig, int mayflush);
|
||||
void tty_task(void);
|
||||
tty_t *line2tty(devminor_t minor);
|
||||
int in_process(struct tty *tp, char *buf, int count, int scode);
|
||||
void out_process(struct tty *tp, char *bstart, char *bpos, char *bend,
|
||||
int *icount, int *ocount);
|
||||
void tty_wakeup(clock_t now);
|
||||
#define tty_reply(c, r, p, s) tty_reply_f(__FILE__, __LINE__, (c), (r), (p), (s))
|
||||
void tty_reply_f(char *f, int l, int code, int replyee, int proc_nr, int
|
||||
status);
|
||||
int select_try(struct tty *tp, int ops);
|
||||
int select_retry(struct tty *tp);
|
||||
|
||||
|
|
@ -161,25 +147,21 @@ void kputc(int c);
|
|||
void cons_stop(void);
|
||||
void scr_init(struct tty *tp);
|
||||
void toggle_scroll(void);
|
||||
int con_loadfont(message *m);
|
||||
int con_loadfont(endpoint_t endpt, cp_grant_id_t grant);
|
||||
void select_console(int cons_line);
|
||||
void beep_x( unsigned freq, clock_t dur);
|
||||
void do_video(message *m);
|
||||
void do_video(message *m, int ipc_status);
|
||||
|
||||
/* keyboard.c */
|
||||
void kb_init(struct tty *tp);
|
||||
void kb_init_once(void);
|
||||
int kbd_loadmap(message *m);
|
||||
int kbd_loadmap(endpoint_t endpt, cp_grant_id_t grant);
|
||||
void do_fkey_ctl(message *m);
|
||||
void kbd_interrupt(message *m);
|
||||
void do_kbd(message *m);
|
||||
void do_kbd(message *m, int ipc_status);
|
||||
void do_kb_inject(message *m);
|
||||
void do_kbdaux(message *m);
|
||||
int kbd_status(message *m_ptr);
|
||||
|
||||
/* pty.c */
|
||||
void do_pty(struct tty *tp, message *m_ptr);
|
||||
void do_pty(message *m_ptr, int ipc_status);
|
||||
void pty_init(struct tty *tp);
|
||||
void select_retry_pty(struct tty *tp);
|
||||
int pty_status(message *m_ptr);
|
||||
|
||||
|
|
|
|||
|
|
@ -60,9 +60,8 @@ static int terminating = 0;
|
|||
static int open_count = 0;
|
||||
|
||||
/* Partition magic */
|
||||
#define VIRTIO_BLK_SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS)
|
||||
struct device part[DEV_PER_DRIVE];
|
||||
struct device subpart[VIRTIO_BLK_SUB_PER_DRIVE];
|
||||
struct device subpart[SUB_PER_DRIVE];
|
||||
|
||||
/* Headers for requests */
|
||||
static struct virtio_blk_outhdr *hdrs_vir;
|
||||
|
|
@ -78,19 +77,19 @@ static u16_t *status_vir;
|
|||
static phys_bytes status_phys;
|
||||
|
||||
/* Prototypes */
|
||||
static int virtio_blk_open(dev_t minor, int access);
|
||||
static int virtio_blk_close(dev_t minor);
|
||||
static ssize_t virtio_blk_transfer(dev_t minor, int write, u64_t position,
|
||||
static int virtio_blk_open(devminor_t minor, int access);
|
||||
static int virtio_blk_close(devminor_t minor);
|
||||
static ssize_t virtio_blk_transfer(devminor_t minor, int write, u64_t position,
|
||||
endpoint_t endpt, iovec_t *iovec,
|
||||
unsigned int cnt, int flags);
|
||||
static int virtio_blk_ioctl(dev_t minor, unsigned int req, endpoint_t endpt,
|
||||
cp_grant_id_t grant);
|
||||
static struct device * virtio_blk_part(dev_t minor);
|
||||
static void virtio_blk_geometry(dev_t minor, struct part_geom *entry);
|
||||
static int virtio_blk_ioctl(devminor_t minor, unsigned long req,
|
||||
endpoint_t endpt, cp_grant_id_t grant, endpoint_t user_endpt);
|
||||
static struct device * virtio_blk_part(devminor_t minor);
|
||||
static void virtio_blk_geometry(devminor_t minor, struct part_geom *entry);
|
||||
static void virtio_blk_device_intr(void);
|
||||
static void virtio_blk_spurious_intr(void);
|
||||
static void virtio_blk_intr(unsigned int irqs);
|
||||
static int virtio_blk_device(dev_t minor, device_id_t *id);
|
||||
static int virtio_blk_device(devminor_t minor, device_id_t *id);
|
||||
|
||||
static int virtio_blk_flush(void);
|
||||
static void virtio_blk_terminate(void);
|
||||
|
|
@ -104,22 +103,19 @@ static int virtio_blk_probe(int skip);
|
|||
|
||||
/* libblockdriver driver tab */
|
||||
static struct blockdriver virtio_blk_dtab = {
|
||||
BLOCKDRIVER_TYPE_DISK,
|
||||
virtio_blk_open,
|
||||
virtio_blk_close,
|
||||
virtio_blk_transfer,
|
||||
virtio_blk_ioctl,
|
||||
NULL, /* bdr_cleanup */
|
||||
virtio_blk_part,
|
||||
virtio_blk_geometry,
|
||||
virtio_blk_intr,
|
||||
NULL, /* bdr_alarm */
|
||||
NULL, /* bdr_other */
|
||||
virtio_blk_device
|
||||
.bdr_type = BLOCKDRIVER_TYPE_DISK,
|
||||
.bdr_open = virtio_blk_open,
|
||||
.bdr_close = virtio_blk_close,
|
||||
.bdr_transfer = virtio_blk_transfer,
|
||||
.bdr_ioctl = virtio_blk_ioctl,
|
||||
.bdr_part = virtio_blk_part,
|
||||
.bdr_geometry = virtio_blk_geometry,
|
||||
.bdr_intr = virtio_blk_intr,
|
||||
.bdr_device = virtio_blk_device
|
||||
};
|
||||
|
||||
static int
|
||||
virtio_blk_open(dev_t minor, int access)
|
||||
virtio_blk_open(devminor_t minor, int access)
|
||||
{
|
||||
struct device *dev = virtio_blk_part(minor);
|
||||
|
||||
|
|
@ -128,7 +124,8 @@ virtio_blk_open(dev_t minor, int access)
|
|||
return ENXIO;
|
||||
|
||||
/* Read only devices should only be mounted... read-only */
|
||||
if ((access & W_BIT) && virtio_host_supports(blk_dev, VIRTIO_BLK_F_RO))
|
||||
if ((access & BDEV_W_BIT) &&
|
||||
virtio_host_supports(blk_dev, VIRTIO_BLK_F_RO))
|
||||
return EACCES;
|
||||
|
||||
/* Partition magic when opened the first time or re-opened after
|
||||
|
|
@ -147,7 +144,7 @@ virtio_blk_open(dev_t minor, int access)
|
|||
}
|
||||
|
||||
static int
|
||||
virtio_blk_close(dev_t minor)
|
||||
virtio_blk_close(devminor_t minor)
|
||||
{
|
||||
struct device *dev = virtio_blk_part(minor);
|
||||
|
||||
|
|
@ -238,8 +235,9 @@ prepare_vir_vec(endpoint_t endpt, struct vumap_vir *vir, iovec_s_t *iv,
|
|||
}
|
||||
|
||||
static ssize_t
|
||||
virtio_blk_transfer(dev_t minor, int write, u64_t position, endpoint_t endpt,
|
||||
iovec_t *iovec, unsigned int cnt, int flags)
|
||||
virtio_blk_transfer(devminor_t minor, int write, u64_t position,
|
||||
endpoint_t endpt, iovec_t *iovec, unsigned int cnt,
|
||||
int flags)
|
||||
{
|
||||
/* Need to translate vir to phys */
|
||||
struct vumap_vir vir[NR_IOREQS];
|
||||
|
|
@ -377,8 +375,8 @@ virtio_blk_transfer(dev_t minor, int write, u64_t position, endpoint_t endpt,
|
|||
}
|
||||
|
||||
static int
|
||||
virtio_blk_ioctl(dev_t minor, unsigned int req, endpoint_t endpt,
|
||||
cp_grant_id_t grant)
|
||||
virtio_blk_ioctl(devminor_t minor, unsigned long req, endpoint_t endpt,
|
||||
cp_grant_id_t grant, endpoint_t UNUSED(user_endpt))
|
||||
{
|
||||
switch (req) {
|
||||
|
||||
|
|
@ -391,28 +389,26 @@ virtio_blk_ioctl(dev_t minor, unsigned int req, endpoint_t endpt,
|
|||
|
||||
}
|
||||
|
||||
return EINVAL;
|
||||
return ENOTTY;
|
||||
}
|
||||
|
||||
static struct device *
|
||||
virtio_blk_part(dev_t minor)
|
||||
virtio_blk_part(devminor_t minor)
|
||||
{
|
||||
/* There's only a single drive attached to this device, alyways.
|
||||
* Lets take some shortcuts...
|
||||
*/
|
||||
|
||||
/* Take care of d0 d0p0 ... */
|
||||
if (minor < 5)
|
||||
if (minor >= 0 && minor < DEV_PER_DRIVE)
|
||||
return &part[minor];
|
||||
|
||||
/* subparts start at 128 */
|
||||
if (minor >= 128) {
|
||||
|
||||
/* Mask away upper bits */
|
||||
minor = minor & 0x7F;
|
||||
/* subparts start at MINOR_d0p0s0 */
|
||||
if (minor >= MINOR_d0p0s0) {
|
||||
minor -= MINOR_d0p0s0;
|
||||
|
||||
/* Only for the first disk */
|
||||
if (minor > 15)
|
||||
if (minor >= SUB_PER_DRIVE)
|
||||
return NULL;
|
||||
|
||||
return &subpart[minor];
|
||||
|
|
@ -422,7 +418,7 @@ virtio_blk_part(dev_t minor)
|
|||
}
|
||||
|
||||
static void
|
||||
virtio_blk_geometry(dev_t minor, struct part_geom *entry)
|
||||
virtio_blk_geometry(devminor_t minor, struct part_geom *entry)
|
||||
{
|
||||
/* Only for the drive */
|
||||
if (minor != 0)
|
||||
|
|
@ -471,7 +467,7 @@ virtio_blk_intr(unsigned int irqs)
|
|||
}
|
||||
|
||||
static int
|
||||
virtio_blk_device(dev_t minor, device_id_t *id)
|
||||
virtio_blk_device(devminor_t minor, device_id_t *id)
|
||||
{
|
||||
struct device *dev = virtio_blk_part(minor);
|
||||
|
||||
|
|
|
|||
12
drivers/vnd/Makefile
Normal file
12
drivers/vnd/Makefile
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Makefile for the VNode Disk driver (VND)
|
||||
PROG= vnd
|
||||
SRCS= vnd.c
|
||||
|
||||
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS}
|
||||
LDADD+= -lblockdriver -lsys
|
||||
|
||||
MAN=
|
||||
|
||||
BINDIR?= /usr/sbin
|
||||
|
||||
.include <minix.service.mk>
|
||||
85
drivers/vnd/NOTES
Normal file
85
drivers/vnd/NOTES
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
Development notes regarding VND. Original document by David van Moolenbroek.
|
||||
|
||||
|
||||
DESIGN DECISIONS
|
||||
|
||||
As simple as the VND driver implementation looks, several important decisions
|
||||
had to be made in the design process. These decisions are listed here.
|
||||
|
||||
Multiple instances instead of a single instance: The decision to spawn a
|
||||
separate driver instance for each VND unit was not ideologically inspired, but
|
||||
rather based on a practical issue. Namely, users may reasonably expect to be
|
||||
able to set up a VND using a backing file that resides on a file system hosted
|
||||
on another VND. If one single driver instance were to host both VND units, its
|
||||
implementation would have to perform all its backcalls to VFS asynchronously,
|
||||
so as to be able to process another incoming request that was initiated as part
|
||||
of such an ongoing backcall. As of writing, MINIX3 does not support any form of
|
||||
asynchronous I/O, but this would not even be sufficient: the asynchrony would
|
||||
have to extend even to the close(2) call that takes place during device
|
||||
unconfiguration, as this call could spark I/O to another VND device.
|
||||
Ultimately, using one driver instance per VND unit avoids these complications
|
||||
altogether, thus making nesting possible with a maximum depth of the number of
|
||||
VFS threads. Of course, this comes at the cost of having more VND driver
|
||||
processes; in order to avoid this cost in the common case, driver instances are
|
||||
dynamically started and stopped by vndconfig(8).
|
||||
|
||||
dupfrom(2) instead of openas(2): Compared to the NetBSD interface, the MINIX3
|
||||
VND API requires that the user program configuring a device pass in a file
|
||||
descriptor in the vnd_ioctl structure instead of a pointer to a path name.
|
||||
While binary compatibility with NetBSD would be impossible anyway (MINIX3 can
|
||||
not support pointers in IOCTL data structures), providing a path name buffer
|
||||
would be closer to what NetBSD does. There are two reasons behind the choice to
|
||||
pass in a file descriptor instead. First, performing an open(2)-like call as
|
||||
a driver backcall is tricky in terms of avoiding deadlocks in VFS, since it
|
||||
would by nature violate the VFS locking order. On top of that, special
|
||||
provisions would have to be added to support opening a file in the context of
|
||||
another process so that chrooted processes would be supported, for example.
|
||||
In contrast, copying a file descriptor to a remote process is relatively easy
|
||||
because there is only one potential deadlock case to cover - that of the given
|
||||
file descriptor identifying the VFS filp object used to control the very same
|
||||
device - and VFS need only implement a procedure that very much resembles
|
||||
sending a file descriptor across a UNIX domain socket. Second, since passing a
|
||||
file descriptor is effectively passing an object capability, it is easier to
|
||||
improve the isolation of the VND drivers in the future, as described below.
|
||||
|
||||
No separate control device: The driver uses the same minor (block) device for
|
||||
configuration and for actual (whole-disk) I/O, instead of exposing a separate
|
||||
device that exists only for the purpose of configuring the device. The reason
|
||||
for this is that such a control device simply does not fit the NetBSD
|
||||
opendisk(3) API. While MINIX3 may at some point implement support for NetBSD's
|
||||
notion of raw devices, such raw devices are still expected to support I/O, and
|
||||
that means they cannot be control-only. In this regard, it should be mentioned
|
||||
that the entire VND infrastructure relies on block caches being invalidated
|
||||
properly upon (un)configuration of VND units, and that such invalidation
|
||||
(through the REQ_FLUSH file system request) is currently initiated only by
|
||||
closing block devices. Support for configuration or I/O through character
|
||||
devices would thus require more work on that side first. In any case, the
|
||||
primary downside of not having a separate control device is that handling
|
||||
access permissions on device open is a bit of a hack in order to keep the
|
||||
MINIX3 userland happy.
|
||||
|
||||
|
||||
FUTURE IMPROVEMENTS
|
||||
|
||||
Currently, the VND driver instances are run as root just and only because the
|
||||
dupfrom(2) call requires root. Obviously, nonroot user processes should never
|
||||
be able to copy file descriptors from arbitrary processes, and thus, some
|
||||
security check is required there. However, an access control list for VFS calls
|
||||
would be a much better solution: in that case, VND driver processes can be
|
||||
given exclusive rights to the use of the dupfrom(2) call, while they can be
|
||||
given a normal driver UID at the same time.
|
||||
|
||||
In MINIX3's dependability model, drivers are generally not considered to be
|
||||
malicious. However, the VND case is interesting because it is possible to
|
||||
isolate individual driver instances to the point of actual "least authority".
|
||||
The dupfrom(2) call currently allows any file descriptor to be copied, but it
|
||||
would be possible to extend the scheme to let user processes (and vndconfig(8)
|
||||
in particular) mark the file descriptors that may be the target of a dupfrom(2)
|
||||
call. One of several schemes may be implemented in VFS for this purpose. For
|
||||
example, each process could be allowed to mark one of its file descriptors as
|
||||
"copyable" using a new VFS call, and VFS would then allow dupfrom(2) only on a
|
||||
"copyable" file descriptor from a process blocked on a call to the driver that
|
||||
invoked dupfrom(2). This approach precludes hiding a VND driver behind a RAID
|
||||
or FBD (etc) driver, but more sophisticated approaches can solve that as well.
|
||||
Regardless of the scheme, the end result would be a situation where the VND
|
||||
drivers are strictly limited to operating on the resources given to them.
|
||||
601
drivers/vnd/vnd.c
Normal file
601
drivers/vnd/vnd.c
Normal file
|
|
@ -0,0 +1,601 @@
|
|||
/* VNode Disk driver, by D.C. van Moolenbroek <david@minix3.org> */
|
||||
|
||||
#include <minix/drivers.h>
|
||||
#include <minix/blockdriver.h>
|
||||
#include <minix/drvlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define VND_BUF_SIZE 65536
|
||||
|
||||
static struct {
|
||||
int fd; /* file descriptor for the underlying file */
|
||||
int openct; /* number of times the device is open */
|
||||
int exiting; /* exit after the last close? */
|
||||
int rdonly; /* is the device set up read-only? */
|
||||
dev_t dev; /* device on which the file resides */
|
||||
ino_t ino; /* inode number of the file */
|
||||
struct device part[DEV_PER_DRIVE]; /* partition bases and sizes */
|
||||
struct device subpart[SUB_PER_DRIVE]; /* same for subpartitions */
|
||||
struct part_geom geom; /* geometry information */
|
||||
char *buf; /* intermediate I/O transfer buffer */
|
||||
} state;
|
||||
|
||||
static unsigned int instance;
|
||||
|
||||
static int vnd_open(devminor_t, int);
|
||||
static int vnd_close(devminor_t);
|
||||
static int vnd_transfer(devminor_t, int, u64_t, endpoint_t, iovec_t *,
|
||||
unsigned int, int);
|
||||
static int vnd_ioctl(devminor_t, unsigned long, endpoint_t, cp_grant_id_t,
|
||||
endpoint_t);
|
||||
static struct device *vnd_part(devminor_t);
|
||||
static void vnd_geometry(devminor_t, struct part_geom *);
|
||||
|
||||
static struct blockdriver vnd_dtab = {
|
||||
.bdr_type = BLOCKDRIVER_TYPE_DISK,
|
||||
.bdr_open = vnd_open,
|
||||
.bdr_close = vnd_close,
|
||||
.bdr_transfer = vnd_transfer,
|
||||
.bdr_ioctl = vnd_ioctl,
|
||||
.bdr_part = vnd_part,
|
||||
.bdr_geometry = vnd_geometry
|
||||
};
|
||||
|
||||
/*
|
||||
* Parse partition tables.
|
||||
*/
|
||||
static void
|
||||
vnd_partition(void)
|
||||
{
|
||||
memset(state.part, 0, sizeof(state.part));
|
||||
memset(state.subpart, 0, sizeof(state.subpart));
|
||||
|
||||
state.part[0].dv_size = state.geom.size;
|
||||
|
||||
partition(&vnd_dtab, 0, P_PRIMARY, FALSE /*atapi*/);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a device.
|
||||
*/
|
||||
static int
|
||||
vnd_open(devminor_t minor, int access)
|
||||
{
|
||||
/* No sub/partition devices are available before initialization. */
|
||||
if (state.fd == -1 && minor != 0)
|
||||
return ENXIO;
|
||||
else if (state.fd != -1 && vnd_part(minor) == NULL)
|
||||
return ENXIO;
|
||||
|
||||
/*
|
||||
* If the device either is not configured or configured as read-only,
|
||||
* block open calls that request write permission. This is what user-
|
||||
* land expects, although it does mean that vnconfig(8) has to open the
|
||||
* device as read-only in order to (un)configure it.
|
||||
*/
|
||||
if (access & BDEV_W_BIT) {
|
||||
if (state.fd == -1)
|
||||
return ENXIO;
|
||||
if (state.rdonly)
|
||||
return EACCES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Userland expects that if the device is opened after having been
|
||||
* fully closed, partition tables are (re)parsed. Since we already
|
||||
* parse partition tables upon initialization, we could skip this for
|
||||
* the first open, but that would introduce more state.
|
||||
*/
|
||||
if (state.fd != -1 && state.openct == 0) {
|
||||
vnd_partition();
|
||||
|
||||
/* Make sure our target device didn't just disappear. */
|
||||
if (vnd_part(minor) == NULL)
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
state.openct++;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close a device.
|
||||
*/
|
||||
static int
|
||||
vnd_close(devminor_t UNUSED(minor))
|
||||
{
|
||||
if (state.openct == 0) {
|
||||
printf("VND%u: closing already-closed device\n", instance);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
state.openct--;
|
||||
|
||||
if (state.exiting)
|
||||
blockdriver_terminate();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a number of bytes from or to the caller, to or from the intermediate
|
||||
* buffer. If the given endpoint is SELF, a local memory copy must be made.
|
||||
*/
|
||||
static int
|
||||
vnd_copy(iovec_s_t *iov, size_t iov_off, size_t bytes, endpoint_t endpt,
|
||||
int do_write)
|
||||
{
|
||||
struct vscp_vec vvec[SCPVEC_NR], *vvp;
|
||||
size_t off, chunk;
|
||||
int count;
|
||||
char *ptr;
|
||||
|
||||
assert(bytes > 0 && bytes <= VND_BUF_SIZE);
|
||||
|
||||
vvp = vvec;
|
||||
count = 0;
|
||||
|
||||
for (off = 0; off < bytes; off += chunk) {
|
||||
chunk = MIN(bytes - off, iov->iov_size - iov_off);
|
||||
|
||||
if (endpt == SELF) {
|
||||
ptr = (char *) iov->iov_grant + iov_off;
|
||||
|
||||
if (do_write)
|
||||
memcpy(&state.buf[off], ptr, chunk);
|
||||
else
|
||||
memcpy(ptr, &state.buf[off], chunk);
|
||||
} else {
|
||||
assert(count < SCPVEC_NR); /* SCPVEC_NR >= NR_IOREQS */
|
||||
|
||||
vvp->v_from = do_write ? endpt : SELF;
|
||||
vvp->v_to = do_write ? SELF : endpt;
|
||||
vvp->v_bytes = chunk;
|
||||
vvp->v_gid = iov->iov_grant;
|
||||
vvp->v_offset = iov_off;
|
||||
vvp->v_addr = (vir_bytes) &state.buf[off];
|
||||
|
||||
vvp++;
|
||||
count++;
|
||||
}
|
||||
|
||||
iov_off += chunk;
|
||||
if (iov_off == iov->iov_size) {
|
||||
iov++;
|
||||
iov_off = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (endpt != SELF)
|
||||
return sys_vsafecopy(vvec, count);
|
||||
else
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Advance the given I/O vector, and the offset into its first element, by the
|
||||
* given number of bytes.
|
||||
*/
|
||||
static iovec_s_t *
|
||||
vnd_advance(iovec_s_t *iov, size_t *iov_offp, size_t bytes)
|
||||
{
|
||||
size_t iov_off;
|
||||
|
||||
assert(bytes > 0 && bytes <= VND_BUF_SIZE);
|
||||
|
||||
iov_off = *iov_offp;
|
||||
|
||||
while (bytes > 0) {
|
||||
if (bytes >= iov->iov_size - iov_off) {
|
||||
bytes -= iov->iov_size - iov_off;
|
||||
iov++;
|
||||
iov_off = 0;
|
||||
} else {
|
||||
iov_off += bytes;
|
||||
bytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
*iov_offp = iov_off;
|
||||
return iov;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform data transfer on the selected device.
|
||||
*/
|
||||
static int
|
||||
vnd_transfer(devminor_t minor, int do_write, u64_t position,
|
||||
endpoint_t endpt, iovec_t *iovt, unsigned int nr_req, int flags)
|
||||
{
|
||||
struct device *dv;
|
||||
iovec_s_t *iov;
|
||||
size_t off, chunk, bytes, iov_off;
|
||||
ssize_t r;
|
||||
unsigned int i;
|
||||
|
||||
iov = (iovec_s_t *) iovt;
|
||||
|
||||
if (state.fd == -1 || (dv = vnd_part(minor)) == NULL)
|
||||
return ENXIO;
|
||||
|
||||
/* Prevent write operations on devices opened as write-only. */
|
||||
if (do_write && state.rdonly)
|
||||
return EACCES;
|
||||
|
||||
/* Determine the total number of bytes to transfer. */
|
||||
if (position >= dv->dv_size)
|
||||
return 0;
|
||||
|
||||
bytes = 0;
|
||||
|
||||
for (i = 0; i < nr_req; i++) {
|
||||
if (iov[i].iov_size == 0 || iov[i].iov_size > LONG_MAX)
|
||||
return EINVAL;
|
||||
bytes += iov[i].iov_size;
|
||||
if (bytes > LONG_MAX)
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (bytes > dv->dv_size - position)
|
||||
bytes = dv->dv_size - position;
|
||||
|
||||
position += dv->dv_base;
|
||||
|
||||
/* Perform the actual transfer, in chunks if necessary. */
|
||||
iov_off = 0;
|
||||
|
||||
for (off = 0; off < bytes; off += chunk) {
|
||||
chunk = MIN(bytes - off, VND_BUF_SIZE);
|
||||
|
||||
assert((unsigned int) (iov - (iovec_s_t *) iovt) < nr_req);
|
||||
|
||||
/* For reads, read in the data for the chunk; possibly less. */
|
||||
if (!do_write) {
|
||||
chunk = r = pread64(state.fd, state.buf, chunk,
|
||||
position);
|
||||
|
||||
if (r < 0) {
|
||||
printf("VND%u: pread failed (%d)\n", instance,
|
||||
-errno);
|
||||
return -errno;
|
||||
}
|
||||
if (r == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy the data for this chunk from or to the caller. */
|
||||
if ((r = vnd_copy(iov, iov_off, chunk, endpt, do_write)) < 0) {
|
||||
printf("VND%u: data copy failed (%d)\n", instance, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* For writes, write the data to the file; possibly less. */
|
||||
if (do_write) {
|
||||
chunk = r = pwrite64(state.fd, state.buf, chunk,
|
||||
position);
|
||||
|
||||
if (r <= 0) {
|
||||
if (r < 0)
|
||||
r = -errno;
|
||||
printf("VND%u: pwrite failed (%d)\n", instance,
|
||||
r);
|
||||
return (r < 0) ? r : EIO;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move ahead on the I/O vector and the file position. */
|
||||
iov = vnd_advance(iov, &iov_off, chunk);
|
||||
|
||||
position += chunk;
|
||||
}
|
||||
|
||||
/* If force-write is requested, flush the underlying file to disk. */
|
||||
if (do_write && (flags & BDEV_FORCEWRITE))
|
||||
fsync(state.fd);
|
||||
|
||||
/* Return the number of bytes transferred. */
|
||||
return off;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the size and geometry for the device and any partitions. If the
|
||||
* user provided a geometry, this will be used; otherwise, a geometry will be
|
||||
* computed.
|
||||
*/
|
||||
static int
|
||||
vnd_layout(u64_t size, struct vnd_ioctl *vnd)
|
||||
{
|
||||
u64_t sectors;
|
||||
|
||||
state.geom.base = 0ULL;
|
||||
|
||||
if (vnd->vnd_flags & VNDIOF_HASGEOM) {
|
||||
/*
|
||||
* The geometry determines the accessible part of the file.
|
||||
* The resulting size must not exceed the file size.
|
||||
*/
|
||||
state.geom.cylinders = vnd->vnd_geom.vng_ncylinders;
|
||||
state.geom.heads = vnd->vnd_geom.vng_ntracks;
|
||||
state.geom.sectors = vnd->vnd_geom.vng_nsectors;
|
||||
|
||||
state.geom.size = (u64_t) state.geom.cylinders *
|
||||
state.geom.heads * state.geom.sectors *
|
||||
vnd->vnd_geom.vng_secsize;
|
||||
if (state.geom.size == 0 || state.geom.size > size)
|
||||
return EINVAL;
|
||||
} else {
|
||||
sectors = size / SECTOR_SIZE;
|
||||
state.geom.size = sectors * SECTOR_SIZE;
|
||||
|
||||
if (sectors >= 32 * 64) {
|
||||
state.geom.cylinders = sectors / (32 * 64);
|
||||
state.geom.heads = 64;
|
||||
state.geom.sectors = 32;
|
||||
} else {
|
||||
state.geom.cylinders = sectors;
|
||||
state.geom.heads = 1;
|
||||
state.geom.sectors = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse partition tables immediately, so that (sub)partitions can be
|
||||
* opened right away. The first open will perform the same procedure,
|
||||
* but that is only necessary to match userland expectations.
|
||||
*/
|
||||
vnd_partition();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process I/O control requests.
|
||||
*/
|
||||
static int
|
||||
vnd_ioctl(devminor_t UNUSED(minor), unsigned long request, endpoint_t endpt,
|
||||
cp_grant_id_t grant, endpoint_t user_endpt)
|
||||
{
|
||||
struct vnd_ioctl vnd;
|
||||
struct vnd_user vnu;
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
switch (request) {
|
||||
case VNDIOCSET:
|
||||
/*
|
||||
* The VND must not be busy. Note that the caller has the
|
||||
* device open to perform the IOCTL request.
|
||||
*/
|
||||
if (state.fd != -1 || state.openct != 1)
|
||||
return EBUSY;
|
||||
|
||||
if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &vnd,
|
||||
sizeof(vnd))) != OK)
|
||||
return r;
|
||||
|
||||
/*
|
||||
* Issue a special VFS backcall that copies a file descriptor
|
||||
* to the current process, from the user process ultimately
|
||||
* making the IOCTL call. The result is either a newly
|
||||
* allocated file descriptor or an error.
|
||||
*/
|
||||
if ((state.fd = dupfrom(user_endpt, vnd.vnd_fildes)) == -1)
|
||||
return -errno;
|
||||
|
||||
/* The target file must be regular. */
|
||||
if (fstat(state.fd, &st) == -1) {
|
||||
printf("VND%u: fstat failed (%d)\n", instance, -errno);
|
||||
r = -errno;
|
||||
}
|
||||
if (r == OK && !S_ISREG(st.st_mode))
|
||||
r = EINVAL;
|
||||
|
||||
/*
|
||||
* Allocate memory for an intermediate I/O transfer buffer. In
|
||||
* order to save on memory in the common case, the buffer is
|
||||
* only allocated when the vnd is in use. We use mmap instead
|
||||
* of malloc to allow the memory to be actually freed later.
|
||||
*/
|
||||
if (r == OK) {
|
||||
state.buf = minix_mmap(NULL, VND_BUF_SIZE, PROT_READ |
|
||||
PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
if (state.buf == MAP_FAILED)
|
||||
r = ENOMEM;
|
||||
}
|
||||
|
||||
if (r != OK) {
|
||||
close(state.fd);
|
||||
state.fd = -1;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Set various device state fields. */
|
||||
state.dev = st.st_dev;
|
||||
state.ino = st.st_ino;
|
||||
state.rdonly = !!(vnd.vnd_flags & VNDIOF_READONLY);
|
||||
|
||||
r = vnd_layout(st.st_size, &vnd);
|
||||
|
||||
/* Upon success, return the device size to userland. */
|
||||
if (r == OK) {
|
||||
vnd.vnd_size = state.geom.size;
|
||||
|
||||
r = sys_safecopyto(endpt, grant, 0, (vir_bytes) &vnd,
|
||||
sizeof(vnd));
|
||||
}
|
||||
|
||||
if (r != OK) {
|
||||
minix_munmap(state.buf, VND_BUF_SIZE);
|
||||
close(state.fd);
|
||||
state.fd = -1;
|
||||
}
|
||||
|
||||
return r;
|
||||
|
||||
case VNDIOCCLR:
|
||||
/* The VND can only be cleared if it has been configured. */
|
||||
if (state.fd == -1)
|
||||
return ENXIO;
|
||||
|
||||
if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &vnd,
|
||||
sizeof(vnd))) != OK)
|
||||
return r;
|
||||
|
||||
/* The caller has the device open to do the IOCTL request. */
|
||||
if (!(vnd.vnd_flags & VNDIOF_FORCE) && state.openct != 1)
|
||||
return EBUSY;
|
||||
|
||||
/*
|
||||
* Close the associated file descriptor immediately, but do not
|
||||
* allow reuse until the device has been closed by the other
|
||||
* users.
|
||||
*/
|
||||
minix_munmap(state.buf, VND_BUF_SIZE);
|
||||
close(state.fd);
|
||||
state.fd = -1;
|
||||
|
||||
return OK;
|
||||
|
||||
case VNDIOCGET:
|
||||
/*
|
||||
* We need not copy in the given structure. It would contain
|
||||
* the requested unit number, but each driver instance provides
|
||||
* only one unit anyway.
|
||||
*/
|
||||
|
||||
memset(&vnu, 0, sizeof(vnu));
|
||||
|
||||
vnu.vnu_unit = instance;
|
||||
|
||||
/* Leave these fields zeroed if the device is not in use. */
|
||||
if (state.fd != -1) {
|
||||
vnu.vnu_dev = state.dev;
|
||||
vnu.vnu_ino = state.ino;
|
||||
}
|
||||
|
||||
return sys_safecopyto(endpt, grant, 0, (vir_bytes) &vnu,
|
||||
sizeof(vnu));
|
||||
|
||||
case DIOCOPENCT:
|
||||
return sys_safecopyto(endpt, grant, 0,
|
||||
(vir_bytes) &state.openct, sizeof(state.openct));
|
||||
|
||||
case DIOCFLUSH:
|
||||
if (state.fd == -1)
|
||||
return ENXIO;
|
||||
|
||||
fsync(state.fd);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
return ENOTTY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a pointer to the partition structure for the given minor device.
|
||||
*/
|
||||
static struct device *
|
||||
vnd_part(devminor_t minor)
|
||||
{
|
||||
if (minor >= 0 && minor < DEV_PER_DRIVE)
|
||||
return &state.part[minor];
|
||||
else if ((unsigned int) (minor -= MINOR_d0p0s0) < SUB_PER_DRIVE)
|
||||
return &state.subpart[minor];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return geometry information.
|
||||
*/
|
||||
static void
|
||||
vnd_geometry(devminor_t UNUSED(minor), struct part_geom *part)
|
||||
{
|
||||
part->cylinders = state.geom.cylinders;
|
||||
part->heads = state.geom.heads;
|
||||
part->sectors = state.geom.sectors;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the device.
|
||||
*/
|
||||
static int
|
||||
vnd_init(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||
{
|
||||
long v;
|
||||
|
||||
/*
|
||||
* No support for crash recovery. The driver would have no way to
|
||||
* reacquire the file descriptor for the target file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The instance number is used for two purposes: reporting errors, and
|
||||
* returning the proper unit number to userland in VNDIOCGET calls.
|
||||
*/
|
||||
v = 0;
|
||||
(void) env_parse("instance", "d", 0, &v, 0, 255);
|
||||
instance = (unsigned int) v;
|
||||
|
||||
state.openct = 0;
|
||||
state.exiting = FALSE;
|
||||
state.fd = -1;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process an incoming signal.
|
||||
*/
|
||||
static void
|
||||
vnd_signal(int signo)
|
||||
{
|
||||
|
||||
/* In case of a termination signal, initiate driver shutdown. */
|
||||
if (signo != SIGTERM)
|
||||
return;
|
||||
|
||||
state.exiting = TRUE;
|
||||
|
||||
/* Keep running until the device has been fully closed. */
|
||||
if (state.openct == 0)
|
||||
blockdriver_terminate();
|
||||
}
|
||||
|
||||
/*
|
||||
* Set callbacks and initialize the System Event Framework (SEF).
|
||||
*/
|
||||
static void
|
||||
vnd_startup(void)
|
||||
{
|
||||
|
||||
/* Register init and signal callbacks. */
|
||||
sef_setcb_init_fresh(vnd_init);
|
||||
sef_setcb_signal_handler(vnd_signal);
|
||||
|
||||
/* Let SEF perform startup. */
|
||||
sef_startup();
|
||||
}
|
||||
|
||||
/*
|
||||
* Driver task.
|
||||
*/
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
||||
/* Initialize the driver. */
|
||||
env_setargs(argc, argv);
|
||||
vnd_startup();
|
||||
|
||||
/* Process requests until shutdown. */
|
||||
blockdriver_task(&vnd_dtab);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -160,6 +160,7 @@
|
|||
|
||||
/set type=dir uid=2 gid=0 mode=755
|
||||
./usr/tests/minix-posix
|
||||
./usr/tests/minix-posix/blocktest
|
||||
|
||||
# this one is for term(1)
|
||||
/set type=dir uid=0 gid=5 mode=775
|
||||
|
|
|
|||
3
etc/rc
3
etc/rc
|
|
@ -171,8 +171,7 @@ start)
|
|||
edit ds
|
||||
edit tty
|
||||
edit memory
|
||||
edit -p log
|
||||
edit -c pfs
|
||||
edit pfs
|
||||
edit init
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -65,10 +65,10 @@ kill_by_name syslogd
|
|||
sleep 3
|
||||
if [ X`/bin/sysenv lwip` = Xyes ]
|
||||
then
|
||||
service up /usr/sbin/lwip -script /etc/rs.inet -dev /dev/ip -devstyle STYLE_CLONE_A
|
||||
service up /usr/sbin/lwip -script /etc/rs.inet -dev /dev/ip
|
||||
dhcpd --lwip &
|
||||
else
|
||||
service up /usr/sbin/inet -script /etc/rs.inet -dev /dev/ip -devstyle STYLE_CLONE
|
||||
service up /usr/sbin/inet -script /etc/rs.inet -dev /dev/ip
|
||||
daemonize dhcpd
|
||||
fi
|
||||
daemonize nonamed -L
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ service mfs
|
|||
{
|
||||
ipc ALL_SYS; # All system ipc targets allowed
|
||||
system BASIC; # Only basic kernel calls allowed
|
||||
vm MAPCACHEPAGE SETCACHEPAGE;
|
||||
vm MAPCACHEPAGE SETCACHEPAGE CLEARCACHE;
|
||||
io NONE; # No I/O range allowed
|
||||
irq NONE; # No IRQ allowed
|
||||
sigmgr rs; # Signal manager is RS
|
||||
|
|
@ -137,7 +137,7 @@ service ext2
|
|||
{
|
||||
ipc ALL_SYS; # All system ipc targets allowed
|
||||
system BASIC; # Only basic kernel calls allowed
|
||||
vm MAPCACHEPAGE SETCACHEPAGE;
|
||||
vm MAPCACHEPAGE SETCACHEPAGE CLEARCACHE;
|
||||
io NONE; # No I/O range allowed
|
||||
irq NONE; # No IRQ allowed
|
||||
sigmgr rs; # Signal manager is RS
|
||||
|
|
@ -150,7 +150,7 @@ service pfs
|
|||
{
|
||||
ipc ALL_SYS; # All system ipc targets allowed
|
||||
system BASIC; # Only basic kernel calls allowed
|
||||
vm MAPCACHEPAGE SETCACHEPAGE;
|
||||
vm MAPCACHEPAGE SETCACHEPAGE CLEARCACHE;
|
||||
io NONE; # No I/O range allowed
|
||||
irq NONE; # No IRQ allowed
|
||||
sigmgr rs; # Signal manager is RS
|
||||
|
|
@ -212,24 +212,8 @@ service memory
|
|||
|
||||
service log
|
||||
{
|
||||
uid 0;
|
||||
ipc ALL_SYS; # All system ipc targets allowed
|
||||
system # Extra kernel calls allowed:
|
||||
UMAP # 14
|
||||
VIRCOPY # 15
|
||||
IRQCTL # 19
|
||||
INT86 # 20
|
||||
DEVIO # 21
|
||||
SDEVIO # 22
|
||||
VDEVIO # 23
|
||||
;
|
||||
vm BASIC; # Only basic VM calls allowed
|
||||
io NONE; # No I/O range allowed
|
||||
irq NONE; # No IRQ allowed
|
||||
sigmgr rs; # Signal manager is RS
|
||||
scheduler sched; # Scheduler is sched
|
||||
priority 2; # priority queue 2
|
||||
quantum 50; # default driver quantum
|
||||
ipc SYSTEM vfs rs vm;
|
||||
priority 2;
|
||||
};
|
||||
|
||||
service init
|
||||
|
|
@ -513,7 +497,7 @@ service osscore
|
|||
4/1 # Multimedia / Audio device
|
||||
;
|
||||
ipc
|
||||
SYSTEM pm rs log tty ds vfs vm
|
||||
SYSTEM pm rs tty ds vfs vm
|
||||
pci inet lwip amddev
|
||||
;
|
||||
uid 0;
|
||||
|
|
@ -539,7 +523,7 @@ service hello
|
|||
DEVIO # 21
|
||||
;
|
||||
ipc
|
||||
SYSTEM pm rs log tty ds vm vfs
|
||||
SYSTEM pm rs tty ds vm vfs
|
||||
pci inet lwip amddev
|
||||
;
|
||||
uid 0;
|
||||
|
|
@ -687,3 +671,11 @@ service fbd
|
|||
bios_wini
|
||||
;
|
||||
};
|
||||
|
||||
service vnd
|
||||
{
|
||||
ipc
|
||||
SYSTEM VFS RS VM
|
||||
;
|
||||
uid 0; # only for dupfrom(2)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ start)
|
|||
|
||||
# Start servers and drivers set at the boot monitor.
|
||||
echo -n "Starting services:"
|
||||
up -n random -dev /dev/random -devstyle STYLE_DEVA -period 3HZ
|
||||
up -n random -dev /dev/random -period 3HZ
|
||||
|
||||
# load random number generator
|
||||
if [ -f $RANDOM_FILE ]
|
||||
|
|
@ -188,13 +188,15 @@ start)
|
|||
done
|
||||
if [ X`/bin/sysenv lwip` = Xyes ]
|
||||
then
|
||||
up lwip -script /etc/rs.inet -dev /dev/ip -devstyle STYLE_CLONE_A
|
||||
up lwip -script /etc/rs.inet -dev /dev/ip
|
||||
else
|
||||
up inet -script /etc/rs.inet -dev /dev/ip -devstyle STYLE_CLONE
|
||||
up inet -script /etc/rs.inet -dev /dev/ip
|
||||
fi
|
||||
|
||||
up -n ipc
|
||||
|
||||
up log -dev /dev/klog
|
||||
|
||||
if [ $ARCH = i386 ]
|
||||
then
|
||||
up -n printer -dev /dev/lp -period 10HZ
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ INCS+= acpi.h audio_fw.h bitmap.h \
|
|||
reboot.h rs.h safecopies.h sched.h sef.h sffs.h \
|
||||
sound.h spin.h sys_config.h sysinfo.h \
|
||||
syslib.h sysutil.h termios.h timers.h type.h \
|
||||
tty.h u64.h usb.h usb_ch9.h vbox.h \
|
||||
u64.h usb.h usb_ch9.h vbox.h \
|
||||
vboxfs.h vboxif.h vboxtype.h vm.h \
|
||||
vfsif.h vtreefs.h libminixfs.h netsock.h \
|
||||
virtio.h
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ int drv_int_sum(void);
|
|||
int drv_int(int sub_dev);
|
||||
int drv_pause(int chan);
|
||||
int drv_resume(int chan);
|
||||
int drv_io_ctl(int request, void * val, int * len, int sub_dev);
|
||||
int drv_io_ctl(unsigned long request, void * val, int * len, int sub_dev);
|
||||
int drv_get_irq(char *irq);
|
||||
int drv_get_frag_size(u32_t *frag_size, int sub_dev);
|
||||
|
||||
|
|
@ -42,11 +42,9 @@ typedef struct {
|
|||
int BufFillNext; /* end of extra circular buffer */
|
||||
int BufLength;
|
||||
int RevivePending; /* process waiting for this dev? */
|
||||
int ReviveStatus; /* return val when proc unblocked */
|
||||
endpoint_t ReviveProcNr; /* the process to unblock */
|
||||
cdev_id_t ReviveId; /* request ID */
|
||||
cp_grant_id_t ReviveGrant; /* grant id associated with io */
|
||||
void *UserBuf; /* address of user's data buffer */
|
||||
int ReadyToRevive; /* are we ready to revive process?*/
|
||||
endpoint_t SourceProcNr; /* process to send notify to (FS) */
|
||||
u32_t FragSize; /* dma fragment size */
|
||||
char *DmaBuf; /* the dma buffer; extra space for
|
||||
|
|
@ -82,9 +80,8 @@ EXTERN special_file_t special_file[];
|
|||
|
||||
#define NO_CHANNEL -1
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define NO_DMA 0
|
||||
|
||||
#define READ_DMA 1
|
||||
#define WRITE_DMA 2
|
||||
|
||||
#endif /* AUDIO_FW_H */
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ extern ssize_t bdev_gather(dev_t dev, u64_t pos, iovec_t *vec, int count,
|
|||
int flags);
|
||||
extern ssize_t bdev_scatter(dev_t dev, u64_t pos, iovec_t *vec, int count,
|
||||
int flags);
|
||||
extern int bdev_ioctl(dev_t dev, int request, void *buf);
|
||||
extern int bdev_ioctl(dev_t dev, int request, void *buf,
|
||||
endpoint_t user_endpt);
|
||||
|
||||
/* Asynchronous API. */
|
||||
typedef int bdev_id_t;
|
||||
|
|
@ -36,7 +37,7 @@ extern bdev_id_t bdev_gather_asyn(dev_t dev, u64_t pos, iovec_t *vec,
|
|||
extern bdev_id_t bdev_scatter_asyn(dev_t dev, u64_t pos, iovec_t *vec,
|
||||
int count, int flags, bdev_callback_t callback, bdev_param_t param);
|
||||
extern bdev_id_t bdev_ioctl_asyn(dev_t dev, int request, void *buf,
|
||||
bdev_callback_t callback, bdev_param_t param);
|
||||
endpoint_t user_endpt, bdev_callback_t callback, bdev_param_t param);
|
||||
|
||||
extern int bdev_wait_asyn(bdev_id_t id);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,19 +15,19 @@ typedef enum {
|
|||
/* Entry points into the device dependent code of block drivers. */
|
||||
struct blockdriver {
|
||||
blockdriver_type_t bdr_type;
|
||||
int(*bdr_open) (dev_t minor, int access);
|
||||
int(*bdr_close) (dev_t minor);
|
||||
ssize_t(*bdr_transfer) (dev_t minor, int do_write, u64_t pos,
|
||||
endpoint_t endpt, iovec_t *iov, unsigned count, int flags);
|
||||
int(*bdr_ioctl) (dev_t minor, unsigned int request, endpoint_t endpt,
|
||||
cp_grant_id_t grant);
|
||||
void(*bdr_cleanup) (void);
|
||||
struct device *(*bdr_part)(dev_t minor);
|
||||
void(*bdr_geometry) (dev_t minor, struct part_geom *part);
|
||||
void(*bdr_intr) (unsigned int irqs);
|
||||
void(*bdr_alarm) (clock_t stamp);
|
||||
int(*bdr_other) (message *m_ptr);
|
||||
int(*bdr_device) (dev_t minor, device_id_t *id);
|
||||
int (*bdr_open)(devminor_t minor, int access);
|
||||
int (*bdr_close)(devminor_t minor);
|
||||
ssize_t (*bdr_transfer)(devminor_t minor, int do_write, u64_t pos,
|
||||
endpoint_t endpt, iovec_t *iov, unsigned int count, int flags);
|
||||
int (*bdr_ioctl)(devminor_t minor, unsigned long request, endpoint_t endpt,
|
||||
cp_grant_id_t grant, endpoint_t user_endpt);
|
||||
void (*bdr_cleanup)(void);
|
||||
struct device *(*bdr_part)(devminor_t minor);
|
||||
void (*bdr_geometry)(devminor_t minor, struct part_geom *part);
|
||||
void (*bdr_intr)(unsigned int mask);
|
||||
void (*bdr_alarm)(clock_t stamp);
|
||||
void (*bdr_other)(message *m_ptr, int ipc_status);
|
||||
int (*bdr_device)(devminor_t minor, device_id_t *id);
|
||||
};
|
||||
|
||||
/* Functions defined by libblockdriver. These can be used for both
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#define BLOCKDRIVER_MT_API 1 /* do not expose the singlethreaded API */
|
||||
#include <minix/blockdriver.h>
|
||||
|
||||
#define BLOCKDRIVER_MAX_DEVICES 32
|
||||
|
||||
void blockdriver_mt_task(struct blockdriver *driver_tab);
|
||||
void blockdriver_mt_sleep(void);
|
||||
void blockdriver_mt_wakeup(thread_id_t id);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#define NCALLS 124 /* number of system calls allowed */
|
||||
#define NCALLS 130 /* number of system calls allowed */
|
||||
|
||||
/* In case it isn't obvious enough: this list is sorted numerically. */
|
||||
#define EXIT 1
|
||||
|
|
@ -49,6 +49,7 @@
|
|||
#define LSTAT 53
|
||||
#define IOCTL 54
|
||||
#define FCNTL 55
|
||||
#define DUPFROM 56
|
||||
#define FS_READY 57
|
||||
#define PIPE2 58
|
||||
#define EXEC 59
|
||||
|
|
@ -72,9 +73,9 @@
|
|||
#define SYSUNAME 78
|
||||
#define GETDENTS 80 /* to VFS */
|
||||
#define LLSEEK 81 /* to VFS */
|
||||
#define FSTATFS 82 /* to VFS */
|
||||
#define STATVFS 83 /* to VFS */
|
||||
#define FSTATVFS 84 /* to VFS */
|
||||
#define GETVFSSTAT 82 /* to VFS */
|
||||
#define STATVFS1 83 /* to VFS */
|
||||
#define FSTATVFS1 84 /* to VFS */
|
||||
#define SELECT 85 /* to VFS */
|
||||
#define FCHDIR 86 /* to VFS */
|
||||
#define FSYNC 87 /* to VFS */
|
||||
|
|
@ -109,8 +110,12 @@
|
|||
|
||||
#define VFS_VMCALL 117
|
||||
|
||||
#define TASK_REPLY 121 /* to VFS: reply code from drivers, not
|
||||
* really a standalone call.
|
||||
*/
|
||||
#define MAPDRIVER 122 /* to VFS, map a device */
|
||||
#define GETRUSAGE 123 /* to PM, VFS */
|
||||
|
||||
#define VFS_PFS_CHECK_PERMS 124 /* to VFS */
|
||||
#define VFS_PFS_VERIFY_FD 125 /* to VFS */
|
||||
#define VFS_PFS_SET_FILP 126 /* to VFS */
|
||||
#define VFS_PFS_COPY_FILP 127 /* to VFS */
|
||||
#define VFS_PFS_PUT_FILP 128 /* to VFS */
|
||||
#define VFS_PFS_CANCEL_FD 129 /* to VFS */
|
||||
|
|
|
|||
|
|
@ -3,39 +3,33 @@
|
|||
|
||||
#include <minix/driver.h>
|
||||
|
||||
typedef unsigned int cdev_id_t;
|
||||
|
||||
/* Entry points into the device dependent code of character drivers. */
|
||||
struct chardriver {
|
||||
int(*cdr_open) (message *m_ptr);
|
||||
int(*cdr_close) (message *m_ptr);
|
||||
int(*cdr_ioctl) (message *m_ptr);
|
||||
struct device *(*cdr_prepare)(dev_t device);
|
||||
int(*cdr_transfer) (endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t *iov, unsigned int nr_req, endpoint_t user_endpt, unsigned int
|
||||
flags);
|
||||
void(*cdr_cleanup) (void);
|
||||
void(*cdr_alarm) (message *m_ptr);
|
||||
int(*cdr_cancel) (message *m_ptr);
|
||||
int(*cdr_select) (message *m_ptr);
|
||||
int(*cdr_other) (message *m_ptr);
|
||||
int (*cdr_open)(devminor_t minor, int access, endpoint_t user_endpt);
|
||||
int (*cdr_close)(devminor_t minor);
|
||||
ssize_t (*cdr_read)(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
ssize_t (*cdr_write)(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
int (*cdr_ioctl)(devminor_t minor, unsigned long request, endpoint_t endpt,
|
||||
cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id);
|
||||
int (*cdr_cancel)(devminor_t minor, endpoint_t endpt, cdev_id_t id);
|
||||
int (*cdr_select)(devminor_t minor, unsigned int ops, endpoint_t endpt);
|
||||
void (*cdr_intr)(unsigned int mask);
|
||||
void (*cdr_alarm)(clock_t stamp);
|
||||
void (*cdr_other)(message *m_ptr, int ipc_status);
|
||||
};
|
||||
|
||||
#define CHARDRIVER_SYNC 0 /* use the synchronous protocol */
|
||||
#define CHARDRIVER_ASYNC 1 /* use the asynchronous protocol */
|
||||
|
||||
#define IS_CDEV_MINOR_RQ(type) (IS_DEV_RQ(type) && (type) != DEV_STATUS)
|
||||
|
||||
/* Functions defined by libchardriver. */
|
||||
void chardriver_announce(void);
|
||||
void chardriver_process(struct chardriver *cdp, int driver_type, message
|
||||
*m_ptr, int ipc_status);
|
||||
void chardriver_process(struct chardriver *cdp, message *m_ptr,
|
||||
int ipc_status);
|
||||
void chardriver_terminate(void);
|
||||
void chardriver_task(struct chardriver *cdp, int driver_type);
|
||||
void chardriver_task(struct chardriver *cdp);
|
||||
|
||||
int do_nop(message *m_ptr);
|
||||
void nop_cleanup(void);
|
||||
void nop_alarm(message *m_ptr);
|
||||
int nop_cancel(message *m_ptr);
|
||||
int nop_select(message *m_ptr);
|
||||
int nop_ioctl(message *m_ptr);
|
||||
void chardriver_reply_task(endpoint_t endpt, cdev_id_t id, int r);
|
||||
void chardriver_reply_select(endpoint_t endpt, devminor_t minor, int ops);
|
||||
|
||||
#endif /* _MINIX_CHARDRIVER_H */
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
* 1 - 0xFF POSIX requests (see callnr.h)
|
||||
* 0x200 - 0x2FF Data link layer requests and responses
|
||||
* 0x300 - 0x3FF Bus controller requests and responses
|
||||
* 0x400 - 0x4FF Character device requests
|
||||
* 0x500 - 0x5FF Character device responses
|
||||
* 0x400 - 0x4FF Character device requests and responses
|
||||
* 0x500 - 0x5FF Block device requests and responses
|
||||
* 0x600 - 0x6FF Kernel calls to SYSTEM task
|
||||
* 0x700 - 0x7FF Reincarnation Server (RS) requests
|
||||
* 0x800 - 0x8FF Data Store (DS) requests
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
* 0x1200 - 0x12FF Devman
|
||||
* 0x1300 - 0x13FF TTY Requests
|
||||
* 0x1400 - 0x14FF VFS-FS transaction IDs
|
||||
* 0x1500 - 0x15FF Block device requests and responses
|
||||
* 0x1500 - 0x15FF (unused)
|
||||
* 0x1600 - 0x16FF VirtualBox (VBOX) requests (see vboxif.h)
|
||||
* 0x1700 - 0x17FF Real Time Clock requests and responses
|
||||
*
|
||||
|
|
@ -74,14 +74,13 @@
|
|||
#define VFS_PROC_NR ((endpoint_t) 1) /* file system */
|
||||
#define RS_PROC_NR ((endpoint_t) 2) /* reincarnation server */
|
||||
#define MEM_PROC_NR ((endpoint_t) 3) /* memory driver (RAM disk, null, etc.) */
|
||||
#define LOG_PROC_NR ((endpoint_t) 4) /* log device driver */
|
||||
#define SCHED_PROC_NR ((endpoint_t) 4) /* scheduler */
|
||||
#define TTY_PROC_NR ((endpoint_t) 5) /* terminal (TTY) driver */
|
||||
#define DS_PROC_NR ((endpoint_t) 6) /* data store server */
|
||||
#define MFS_PROC_NR ((endpoint_t) 7) /* minix root filesystem */
|
||||
#define VM_PROC_NR ((endpoint_t) 8) /* memory server */
|
||||
#define PFS_PROC_NR ((endpoint_t) 9) /* pipe filesystem */
|
||||
#define SCHED_PROC_NR ((endpoint_t) 10) /* scheduler */
|
||||
#define LAST_SPECIAL_PROC_NR 11 /* An untyped version for
|
||||
#define LAST_SPECIAL_PROC_NR 10 /* An untyped version for
|
||||
computation in macros.*/
|
||||
#define INIT_PROC_NR ((endpoint_t) LAST_SPECIAL_PROC_NR) /* init
|
||||
-- goes multiuser */
|
||||
|
|
@ -182,70 +181,9 @@
|
|||
*/
|
||||
|
||||
#define BUSC_I2C_RESERVE (BUSC_RQ_BASE + 64) /* reserve i2c device */
|
||||
#define BUSC_I2C_ADDR m2_i1 /* slave address */
|
||||
#define BUSC_I2C_EXEC (BUSC_RQ_BASE + 65) /* perform i2c action */
|
||||
|
||||
/*===========================================================================*
|
||||
* Messages for CHARACTER device drivers *
|
||||
*===========================================================================*/
|
||||
|
||||
/* Message types for character device drivers. */
|
||||
#define DEV_RQ_BASE 0x400 /* base for character device request types */
|
||||
#define DEV_RS_BASE 0x500 /* base for character device response types */
|
||||
|
||||
#define CANCEL (DEV_RQ_BASE + 0) /* force a task to cancel */
|
||||
#define DEV_OPEN (DEV_RQ_BASE + 6) /* open a minor device */
|
||||
#define DEV_CLOSE (DEV_RQ_BASE + 7) /* close a minor device */
|
||||
#define DEV_SELECT (DEV_RQ_BASE + 12) /* request select() attention */
|
||||
#define DEV_STATUS (DEV_RQ_BASE + 13) /* request driver status */
|
||||
#define DEV_REOPEN (DEV_RQ_BASE + 14) /* reopen a minor device */
|
||||
|
||||
#define DEV_READ_S (DEV_RQ_BASE + 20) /* (safecopy) read from minor */
|
||||
#define DEV_WRITE_S (DEV_RQ_BASE + 21) /* (safecopy) write to minor */
|
||||
#define DEV_SCATTER_S (DEV_RQ_BASE + 22) /* (safecopy) write from a vector */
|
||||
#define DEV_GATHER_S (DEV_RQ_BASE + 23) /* (safecopy) read into a vector */
|
||||
#define DEV_IOCTL_S (DEV_RQ_BASE + 24) /* (safecopy) I/O control code */
|
||||
|
||||
#define IS_DEV_RQ(type) (((type) & ~0xff) == DEV_RQ_BASE)
|
||||
|
||||
#define DEV_REVIVE (DEV_RS_BASE + 2) /* driver revives process */
|
||||
#define DEV_IO_READY (DEV_RS_BASE + 3) /* selected device ready */
|
||||
#define DEV_NO_STATUS (DEV_RS_BASE + 4) /* empty status reply */
|
||||
#define DEV_REOPEN_REPL (DEV_RS_BASE + 5) /* reply to DEV_REOPEN */
|
||||
#define DEV_CLOSE_REPL (DEV_RS_BASE + 6) /* reply to DEV_CLOSE */
|
||||
#define DEV_SEL_REPL1 (DEV_RS_BASE + 7) /* first reply to DEV_SELECT */
|
||||
#define DEV_SEL_REPL2 (DEV_RS_BASE + 8) /* (opt) second reply to DEV_SELECT */
|
||||
#define DEV_OPEN_REPL (DEV_RS_BASE + 9) /* reply to DEV_OPEN */
|
||||
|
||||
#define IS_DEV_RS(type) (((type) & ~0xff) == DEV_RS_BASE)
|
||||
|
||||
/* Field names for messages to character device drivers. */
|
||||
#define DEVICE m2_i1 /* major-minor device */
|
||||
#define USER_ENDPT m2_i2 /* which endpoint initiated this call? */
|
||||
#define COUNT m2_i3 /* how many bytes to transfer */
|
||||
#define REQUEST m2_i3 /* ioctl request code */
|
||||
#define POSITION m2_l1 /* file offset (low 4 bytes) */
|
||||
#define HIGHPOS m2_l2 /* file offset (high 4 bytes) */
|
||||
#define ADDRESS m2_p1 /* core buffer address */
|
||||
#define IO_GRANT m2_p1 /* grant id (for DEV_*_S variants) */
|
||||
#define FLAGS m2_s1 /* operation flags */
|
||||
|
||||
#define FLG_OP_NONBLOCK 0x1 /* operation is non blocking */
|
||||
|
||||
/* Field names for DEV_SELECT messages to character device drivers. */
|
||||
#define DEV_MINOR m2_i1 /* minor device */
|
||||
#define DEV_SEL_OPS m2_i2 /* which select operations are requested */
|
||||
|
||||
/* Field names used in reply messages from tasks. */
|
||||
#define REP_ENDPT m2_i1 /* # of proc on whose behalf I/O was done */
|
||||
#define REP_STATUS m2_i2 /* bytes transferred or error number */
|
||||
#define REP_IO_GRANT m2_i3 /* DEV_REVIVE: grant by which I/O was done */
|
||||
# define SUSPEND -998 /* status to suspend caller, reply later */
|
||||
|
||||
/* Field names for messages to TTY driver. */
|
||||
#define TTY_LINE DEVICE /* message parameter: terminal line */
|
||||
#define TTY_REQUEST COUNT /* message parameter: ioctl request code */
|
||||
#define TTY_SPEK POSITION/* message parameter: ioctl speed, erasing */
|
||||
#define TTY_PGRP m2_i3 /* message parameter: process group */
|
||||
#define BUSC_I2C_GRANT m2_i1 /* grant for request */
|
||||
|
||||
/*===========================================================================*
|
||||
* Messages for networking layer *
|
||||
|
|
@ -344,7 +282,8 @@
|
|||
# define SYS_SETTIME (KERNEL_CALL + 40) /* sys_settime() */
|
||||
|
||||
# define SYS_VMCTL (KERNEL_CALL + 43) /* sys_vmctl() */
|
||||
# define SYS_SYSCTL (KERNEL_CALL + 44) /* sys_sysctl() */
|
||||
|
||||
# define SYS_DIAGCTL (KERNEL_CALL + 44) /* sys_diagctl() */
|
||||
|
||||
# define SYS_VTIMER (KERNEL_CALL + 45) /* sys_vtimer() */
|
||||
# define SYS_RUNCTL (KERNEL_CALL + 46) /* sys_runctl() */
|
||||
|
|
@ -370,7 +309,7 @@
|
|||
#define SYS_BASIC_CALLS \
|
||||
SYS_EXIT, SYS_SAFECOPYFROM, SYS_SAFECOPYTO, SYS_VSAFECOPY, SYS_GETINFO, \
|
||||
SYS_TIMES, SYS_SETALARM, SYS_SETGRANT, \
|
||||
SYS_PROFBUF, SYS_SYSCTL, SYS_STATECTL, SYS_SAFEMEMSET
|
||||
SYS_PROFBUF, SYS_DIAGCTL, SYS_STATECTL, SYS_SAFEMEMSET
|
||||
|
||||
/* Field names for SYS_MEMSET. */
|
||||
#define MEM_PTR m2_p1 /* base */
|
||||
|
|
@ -644,12 +583,14 @@
|
|||
#define VMCTL_CLEARMAPCACHE 32
|
||||
#define VMCTL_BOOTINHIBIT_CLEAR 33
|
||||
|
||||
/* Codes and field names for SYS_SYSCTL. */
|
||||
#define SYSCTL_CODE m1_i1 /* SYSCTL_CODE_* below */
|
||||
#define SYSCTL_ARG1 m1_p1
|
||||
#define SYSCTL_ARG2 m1_i2
|
||||
#define SYSCTL_CODE_DIAG 1 /* Print diagnostics. */
|
||||
#define SYSCTL_CODE_STACKTRACE 2 /* Print process stack. */
|
||||
/* Codes and field names for SYS_DIAGCTL. */
|
||||
#define DIAGCTL_CODE m1_i1 /* DIAGCTL_CODE_* below */
|
||||
#define DIAGCTL_ARG1 m1_p1
|
||||
#define DIAGCTL_ARG2 m1_i2
|
||||
#define DIAGCTL_CODE_DIAG 1 /* Print diagnostics. */
|
||||
#define DIAGCTL_CODE_STACKTRACE 2 /* Print process stack. */
|
||||
#define DIAGCTL_CODE_REGISTER 3 /* Register for diagnostic signals */
|
||||
#define DIAGCTL_CODE_UNREGISTER 4 /* Unregister for diagnostic signals */
|
||||
#define DIAG_BUFSIZE (80*25)
|
||||
|
||||
/* Field names for SYS_VTIMER. */
|
||||
|
|
@ -825,7 +766,6 @@
|
|||
|
||||
/* Additional parameters for PM_DUMPCORE */
|
||||
# define PM_TERM_SIG m7_i2 /* process's termination signal */
|
||||
# define PM_TRACED_PROC m7_i3 /* required for T_DUMPCORE */
|
||||
|
||||
/* Parameters for the EXEC_NEWMEM call */
|
||||
#define EXC_NM_PROC m1_i1 /* process that needs new map */
|
||||
|
|
@ -902,14 +842,59 @@
|
|||
#define SEL_ERRORFDS m8_p3
|
||||
#define SEL_TIMEOUT m8_p4
|
||||
|
||||
/* Field names for the fstatvfs call */
|
||||
#define FSTATVFS_FD m1_i1
|
||||
#define FSTATVFS_BUF m1_p1
|
||||
/* Field names for the getvfsstat(2) call. */
|
||||
#define VFS_GETVFSSTAT_BUF m1_p1
|
||||
#define VFS_GETVFSSTAT_SIZE m1_i1
|
||||
#define VFS_GETVFSSTAT_FLAGS m1_i2
|
||||
|
||||
/* Field names for the statvfs call */
|
||||
#define STATVFS_LEN m1_i1
|
||||
#define STATVFS_NAME m1_p1
|
||||
#define STATVFS_BUF m1_p2
|
||||
/* Field names for the fstatvfs1(2) call. */
|
||||
#define VFS_FSTATVFS1_FD m1_i1
|
||||
#define VFS_FSTATVFS1_BUF m1_p1
|
||||
#define VFS_FSTATVFS1_FLAGS m1_i2
|
||||
|
||||
/* Field names for the statvfs1(2) call. */
|
||||
#define VFS_STATVFS1_LEN m1_i1
|
||||
#define VFS_STATVFS1_NAME m1_p1
|
||||
#define VFS_STATVFS1_BUF m1_p2
|
||||
#define VFS_STATVFS1_FLAGS m1_i2
|
||||
|
||||
/* Field names for the mount(2) call. */
|
||||
#define VFS_MOUNT_FLAGS m11_i1
|
||||
#define VFS_MOUNT_DEVLEN m11_s1
|
||||
#define VFS_MOUNT_PATHLEN m11_s2
|
||||
#define VFS_MOUNT_TYPELEN m11_s3
|
||||
#define VFS_MOUNT_LABELLEN m11_s4
|
||||
#define VFS_MOUNT_DEV m11_p1
|
||||
#define VFS_MOUNT_PATH m11_p2
|
||||
#define VFS_MOUNT_TYPE m11_p3
|
||||
#define VFS_MOUNT_LABEL m11_p4
|
||||
|
||||
/* Field names for the umount(2) call. */
|
||||
#define VFS_UMOUNT_NAME m1_p1
|
||||
#define VFS_UMOUNT_NAMELEN m1_i1
|
||||
#define VFS_UMOUNT_LABEL m1_p2
|
||||
#define VFS_UMOUNT_LABELLEN m1_i2
|
||||
|
||||
/* Field names for the ioctl(2) call. */
|
||||
#define VFS_IOCTL_FD m2_i1
|
||||
#define VFS_IOCTL_REQ m2_i3
|
||||
#define VFS_IOCTL_ARG m2_p1
|
||||
|
||||
/* Field names for the PFS backcalls to VFS. */
|
||||
#define VFS_PFS_ENDPT m2_i1
|
||||
#define VFS_PFS_GRANT m2_i2
|
||||
#define VFS_PFS_COUNT m2_i3
|
||||
#define VFS_PFS_FD m2_i3
|
||||
#define VFS_PFS_FILP m2_p1
|
||||
|
||||
/* Field names for the dupfrom(2) call. */
|
||||
#define VFS_DUPFROM_ENDPT m1_i1
|
||||
#define VFS_DUPFROM_FD m1_i2
|
||||
|
||||
/* Field names for GETRUSAGE related calls */
|
||||
#define RU_ENDPT m1_i1 /* indicates a process for sys_getrusage */
|
||||
#define RU_WHO m1_i1 /* who argument in getrusage call */
|
||||
#define RU_RUSAGE_ADDR m1_p1 /* pointer to struct rusage */
|
||||
|
||||
/*===========================================================================*
|
||||
* Messages for VM server *
|
||||
|
|
@ -997,6 +982,9 @@
|
|||
/* To VM: identify cache block in FS */
|
||||
#define VM_SETCACHEPAGE (VM_RQ_BASE+27)
|
||||
|
||||
/* To VM: clear all cache blocks for a device */
|
||||
#define VM_CLEARCACHE (VM_RQ_BASE+28)
|
||||
|
||||
/* To VFS: fields for request from VM. */
|
||||
# define VFS_VMCALL_REQ m10_i1
|
||||
# define VFS_VMCALL_FD m10_i2
|
||||
|
|
@ -1252,7 +1240,6 @@
|
|||
|
||||
|
||||
#define TTY_FKEY_CONTROL (TTY_RQ_BASE + 1) /* control an F-key at TTY */
|
||||
#define OLD_FKEY_CONTROL 98 /* previously used for TTY_FKEY_CONTROL */
|
||||
# define FKEY_REQUEST m2_i1 /* request to perform at TTY */
|
||||
# define FKEY_MAP 10 /* observe function key */
|
||||
# define FKEY_UNMAP 11 /* stop observing function key */
|
||||
|
|
@ -1271,13 +1258,71 @@
|
|||
#define VFS_TRANSID (VFS_TRANSACTION_BASE + 1)
|
||||
#define IS_VFS_FS_TRANSID(type) (((type) & ~0xff) == VFS_TRANSACTION_BASE)
|
||||
|
||||
/*===========================================================================*
|
||||
* Messages for character devices *
|
||||
*===========================================================================*/
|
||||
|
||||
/* Base type for character device requests and responses. */
|
||||
#define CDEV_RQ_BASE 0x400
|
||||
#define CDEV_RS_BASE 0x480
|
||||
|
||||
#define IS_CDEV_RQ(type) (((type) & ~0x7f) == CDEV_RQ_BASE)
|
||||
#define IS_CDEV_RS(type) (((type) & ~0x7f) == CDEV_RS_BASE)
|
||||
|
||||
/* Message types for character device requests. */
|
||||
#define CDEV_OPEN (CDEV_RQ_BASE + 0) /* open a minor device */
|
||||
#define CDEV_CLOSE (CDEV_RQ_BASE + 1) /* close a minor device */
|
||||
#define CDEV_READ (CDEV_RQ_BASE + 2) /* read into a buffer */
|
||||
#define CDEV_WRITE (CDEV_RQ_BASE + 3) /* write from a buffer */
|
||||
#define CDEV_IOCTL (CDEV_RQ_BASE + 4) /* I/O control operation */
|
||||
#define CDEV_CANCEL (CDEV_RQ_BASE + 5) /* cancel suspended request */
|
||||
#define CDEV_SELECT (CDEV_RQ_BASE + 6) /* test for ready operations */
|
||||
|
||||
/* Message types for character device responses. */
|
||||
#define CDEV_REPLY (CDEV_RS_BASE + 0) /* general reply code */
|
||||
#define CDEV_SEL1_REPLY (CDEV_RS_BASE + 1) /* immediate select reply */
|
||||
#define CDEV_SEL2_REPLY (CDEV_RS_BASE + 2) /* select notification reply */
|
||||
|
||||
/* Field names for block device messages. */
|
||||
#define CDEV_MINOR m10_i1 /* minor device number */
|
||||
#define CDEV_STATUS m10_i2 /* OK, error code, minor device, operations */
|
||||
#define CDEV_ACCESS m10_i2 /* access bits for open requests */
|
||||
#define CDEV_GRANT m10_i2 /* grant ID of buffer */
|
||||
#define CDEV_OPS m10_i2 /* requested select operations */
|
||||
#define CDEV_COUNT m10_i3 /* number of bytes to transfer */
|
||||
#define CDEV_USER m10_i3 /* endpoint of user process */
|
||||
#define CDEV_FLAGS m10_i4 /* transfer flags */
|
||||
#define CDEV_ID m10_l1 /* opaque request ID */
|
||||
#define CDEV_REQUEST m10_l2 /* I/O control request */
|
||||
#define CDEV_POS_LO m10_l2 /* transfer position (low bits) */
|
||||
#define CDEV_POS_HI m10_l3 /* transfer position (high bits) */
|
||||
|
||||
/* Bits in 'CDEV_ACCESS' field of block device open requests. */
|
||||
# define CDEV_R_BIT 0x01 /* open with read access */
|
||||
# define CDEV_W_BIT 0x02 /* open with write access */
|
||||
# define CDEV_NOCTTY 0x04 /* not to become the controlling TTY */
|
||||
|
||||
/* Bits in 'CDEV_FLAGS' field of block device transfer requests. */
|
||||
# define CDEV_NOFLAGS 0x00 /* no flags are set */
|
||||
# define CDEV_NONBLOCK 0x01 /* do not suspend I/O request */
|
||||
|
||||
/* Bits in 'CDEV_OPS', 'CDEV_STATUS' fields of block device select messages. */
|
||||
# define CDEV_OP_RD 0x01 /* selected for read operation */
|
||||
# define CDEV_OP_WR 0x02 /* selected for write operation */
|
||||
# define CDEV_OP_ERR 0x04 /* selected for error operation */
|
||||
# define CDEV_NOTIFY 0x08 /* notification requested */
|
||||
|
||||
/* Bits in 'CDEV_STATUS' field of block device open responses. */
|
||||
# define CDEV_CLONED 0x20000000 /* device is cloned */
|
||||
# define CDEV_CTTY 0x40000000 /* device is controlling TTY */
|
||||
|
||||
/*===========================================================================*
|
||||
* Messages for block devices *
|
||||
*===========================================================================*/
|
||||
|
||||
/* Base type for block device requests and responses. */
|
||||
#define BDEV_RQ_BASE 0x1500
|
||||
#define BDEV_RS_BASE 0x1580
|
||||
#define BDEV_RQ_BASE 0x500
|
||||
#define BDEV_RS_BASE 0x580
|
||||
|
||||
#define IS_BDEV_RQ(type) (((type) & ~0x7f) == BDEV_RQ_BASE)
|
||||
#define IS_BDEV_RS(type) (((type) & ~0x7f) == BDEV_RS_BASE)
|
||||
|
|
@ -1298,24 +1343,24 @@
|
|||
#define BDEV_MINOR m10_i1 /* minor device number */
|
||||
#define BDEV_STATUS m10_i1 /* OK or error code */
|
||||
#define BDEV_ACCESS m10_i2 /* access bits for open requests */
|
||||
#define BDEV_REQUEST m10_i2 /* I/O control request */
|
||||
#define BDEV_COUNT m10_i2 /* number of bytes or elements in transfer */
|
||||
#define BDEV_GRANT m10_i3 /* grant ID of buffer or vector */
|
||||
#define BDEV_FLAGS m10_i4 /* transfer flags */
|
||||
#define BDEV_USER m10_i4 /* user endpoint requesting I/O control */
|
||||
#define BDEV_ID m10_l1 /* opaque request ID */
|
||||
#define BDEV_REQUEST m10_l2 /* I/O control request */
|
||||
#define BDEV_POS_LO m10_l2 /* transfer position (low bits) */
|
||||
#define BDEV_POS_HI m10_l3 /* transfer position (high bits) */
|
||||
|
||||
/* Bits in 'BDEV_ACCESS' field of block device open requests. */
|
||||
# define BDEV_R_BIT 0x01 /* open with read access */
|
||||
# define BDEV_W_BIT 0x02 /* open with write access */
|
||||
|
||||
/* Bits in 'BDEV_FLAGS' field of block device transfer requests. */
|
||||
# define BDEV_NOFLAGS 0x00 /* no flags are set */
|
||||
# define BDEV_FORCEWRITE 0x01 /* force write to disk immediately */
|
||||
# define BDEV_NOPAGE 0x02 /* eeprom: don't send page address */
|
||||
|
||||
/* Field names for GETRUSAGE related calls */
|
||||
#define RU_ENDPT m1_i1 /* indicates a process for sys_getrusage */
|
||||
#define RU_WHO m1_i1 /* who argument in getrusage call */
|
||||
#define RU_RUSAGE_ADDR m1_p1 /* pointer to struct rusage */
|
||||
|
||||
/*===========================================================================*
|
||||
* Messages for Real Time Clocks *
|
||||
*===========================================================================*/
|
||||
|
|
@ -1350,4 +1395,10 @@
|
|||
#define RTCDEV_Y2KBUG 0x01 /* Interpret 1980 as 2000 for RTC w/Y2K bug */
|
||||
#define RTCDEV_CMOSREG 0x02 /* Also set the CMOS clock register bits. */
|
||||
|
||||
/*===========================================================================*
|
||||
* Internal codes used by several services *
|
||||
*===========================================================================*/
|
||||
|
||||
#define SUSPEND -998 /* status to suspend caller, reply later */
|
||||
|
||||
/* _MINIX_COM_H */
|
||||
|
|
|
|||
|
|
@ -35,17 +35,6 @@
|
|||
/* DMA_SECTORS may be increased to speed up DMA based drivers. */
|
||||
#define DMA_SECTORS 1 /* DMA buffer size (must be >= 1) */
|
||||
|
||||
/* Which processes should receive diagnostics from the kernel and system?
|
||||
* Directly sending it to TTY only displays the output. Sending it to the
|
||||
* log driver will cause the diagnostics to be buffered and displayed.
|
||||
* Messages are sent by src/lib/sysutil/kputc.c to these processes, in
|
||||
* the order of this array, which must be terminated by NONE. This is used
|
||||
* by drivers and servers that printf().
|
||||
* The kernel does this for its own kprintf() in kernel/utility.c, also using
|
||||
* this array, but a slightly different mechanism.
|
||||
*/
|
||||
#define OUTPUT_PROCS_ARRAY { TTY_PROC_NR, LOG_PROC_NR, NONE }
|
||||
|
||||
/* NR_CONS, NR_RS_LINES, and NR_PTYS determine the number of terminals the
|
||||
* system can handle.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -4,12 +4,8 @@
|
|||
#include <minix/sys_config.h>
|
||||
#include <minix/ipc.h>
|
||||
|
||||
enum dev_style { STYLE_NDEV, STYLE_DEV, STYLE_DEVA, STYLE_TTY, STYLE_CTTY,
|
||||
STYLE_CLONE, STYLE_CLONE_A };
|
||||
#define IS_DEV_STYLE(s) (s>=STYLE_NDEV && s<=STYLE_CLONE_A)
|
||||
|
||||
#define dev_style_asyn(devstyle) ((devstyle) == STYLE_DEVA || \
|
||||
(devstyle) == STYLE_CLONE_A)
|
||||
enum dev_style { STYLE_NDEV, STYLE_DEV, STYLE_TTY, STYLE_CTTY };
|
||||
#define IS_DEV_STYLE(s) (s>=STYLE_NDEV && s<=STYLE_CTTY)
|
||||
|
||||
/*===========================================================================*
|
||||
* Major and minor device numbers *
|
||||
|
|
@ -75,7 +71,7 @@ enum dev_style { STYLE_NDEV, STYLE_DEV, STYLE_DEVA, STYLE_TTY, STYLE_CTTY,
|
|||
#define BMP085B1S77_MAJOR 53 /* 53 = /dev/bmp085b1s77 (bmp085) */
|
||||
#define BMP085B2S77_MAJOR 54 /* 54 = /dev/bmp085b2s77 (bmp085) */
|
||||
#define BMP085B3S77_MAJOR 55 /* 55 = /dev/bmp085b3s77 (bmp085) */
|
||||
|
||||
/* 56-63 = /dev/vnd[0-7] (vnd) */
|
||||
|
||||
/* Minor device numbers for memory driver. */
|
||||
# define RAM_DEV_OLD 0 /* minor device for /dev/ram */
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ void partition(struct blockdriver *bdr, int device, int style, int
|
|||
atapi);
|
||||
|
||||
#define DEV_PER_DRIVE (1 + NR_PARTITIONS)
|
||||
#define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS)
|
||||
#define MINOR_t0 64
|
||||
#define MINOR_r0 120
|
||||
#define MINOR_d0p0s0 128
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
_IOC_IN)
|
||||
#define _IORW(x,y,t) ((x << 8) | y | ((sizeof(t) & _IOCPARM_MASK) << 16) |\
|
||||
_IOC_INOUT)
|
||||
#define _IOWR(x,y,t) _IORW(x,y,t) /* NetBSD compatibility */
|
||||
|
||||
#define _IOW_BIG(y,t) (y | ((sizeof(t) & _IOCPARM_MASK_BIG) << 8) \
|
||||
| _IOC_IN | _IOC_BIG)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ typedef struct {long m9l1, m9l2, m9l3, m9l4, m9l5;
|
|||
short m9s1, m9s2, m9s3, m9s4; } mess_9;
|
||||
typedef struct {int m10i1, m10i2, m10i3, m10i4;
|
||||
long m10l1, m10l2, m10l3; } mess_10;
|
||||
typedef struct {int m11i1; short m11s1, m11s2, m11s3, m11s4;
|
||||
char *m11p1, *m11p2, *m11p3, *m11p4; } mess_11;
|
||||
|
||||
typedef struct {
|
||||
void *block;
|
||||
|
|
@ -68,6 +70,7 @@ typedef struct {
|
|||
mess_6 m_m6;
|
||||
mess_9 m_m9;
|
||||
mess_10 m_m10;
|
||||
mess_11 m_m11;
|
||||
mess_vmmcp m_vmmcp;
|
||||
mess_vmmcp_reply m_vmmcp_reply;
|
||||
mess_vm_vfs_mmap m_vm_vfs;
|
||||
|
|
@ -154,6 +157,16 @@ typedef struct {
|
|||
#define m10_l2 m_u.m_m10.m10l2
|
||||
#define m10_l3 m_u.m_m10.m10l3
|
||||
|
||||
#define m11_i1 m_u.m_m11.m11i1
|
||||
#define m11_s1 m_u.m_m11.m11s1
|
||||
#define m11_s2 m_u.m_m11.m11s2
|
||||
#define m11_s3 m_u.m_m11.m11s3
|
||||
#define m11_s4 m_u.m_m11.m11s4
|
||||
#define m11_p1 m_u.m_m11.m11p1
|
||||
#define m11_p2 m_u.m_m11.m11p2
|
||||
#define m11_p3 m_u.m_m11.m11p3
|
||||
#define m11_p4 m_u.m_m11.m11p4
|
||||
|
||||
/*==========================================================================*
|
||||
* Minix run-time system (IPC). *
|
||||
*==========================================================================*/
|
||||
|
|
|
|||
|
|
@ -5,16 +5,16 @@
|
|||
#ifndef _MOUNT_H
|
||||
#define _MOUNT_H
|
||||
|
||||
#define MS_RDONLY 0x001 /* Mount device read only */
|
||||
#define MS_REUSE 0x002 /* Tell RS to try reusing binary from memory */
|
||||
#define MS_LABEL16 0x004 /* Mount message points to 16-byte label */
|
||||
#define MS_EXISTING 0x008 /* Tell mount to use already running server */
|
||||
/* Service flags. These are not passed to VFS. */
|
||||
#define MS_REUSE 0x001 /* Tell RS to try reusing binary from memory */
|
||||
#define MS_EXISTING 0x002 /* Tell mount to use already running server */
|
||||
|
||||
/* Legacy definitions. */
|
||||
#define MNTNAMELEN 16 /* Length of fs type name including nul */
|
||||
#define MNTFLAGLEN 64 /* Length of flags string including nul */
|
||||
|
||||
int mount(char *_spec, char *_name, int _mountflags, char *type, char
|
||||
*args);
|
||||
int umount(const char *_name);
|
||||
int umount2(const char *_name, int flags);
|
||||
int mount(char *_spec, char *_name, int _mountflags, int srvflags, char *type,
|
||||
char *args);
|
||||
int umount(const char *_name, int srvflags);
|
||||
|
||||
#endif /* _MOUNT_H */
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <minix/ipc.h>
|
||||
#include <minix/endpoint.h>
|
||||
#include <minix/chardriver.h>
|
||||
|
||||
/*
|
||||
* User can set this variable to make the debugging output differ between
|
||||
|
|
@ -18,19 +19,21 @@ extern char * netsock_user_name;
|
|||
#define SOCK_TYPES 3
|
||||
|
||||
struct socket;
|
||||
struct sock_req;
|
||||
|
||||
typedef void (* sock_op_t)(struct socket *, message *);
|
||||
typedef void (* sock_op_io_t)(struct socket *, message *, int blk);
|
||||
typedef int (* sock_op_open_t)(struct socket *, message *);
|
||||
typedef int (* sock_op_opcl_t)(struct socket *);
|
||||
typedef int (* sock_op_io_t)(struct socket *, struct sock_req *, int blk);
|
||||
typedef int (* sock_op_select_t)(struct socket *, unsigned int);
|
||||
typedef int (* sock_op_select_reply_t)(struct socket *);
|
||||
|
||||
struct sock_ops {
|
||||
sock_op_open_t open;
|
||||
sock_op_t close;
|
||||
sock_op_io_t read;
|
||||
sock_op_io_t write;
|
||||
sock_op_io_t ioctl;
|
||||
sock_op_t select;
|
||||
sock_op_t select_reply;
|
||||
sock_op_opcl_t open;
|
||||
sock_op_opcl_t close;
|
||||
sock_op_io_t read;
|
||||
sock_op_io_t write;
|
||||
sock_op_io_t ioctl;
|
||||
sock_op_select_t select;
|
||||
sock_op_select_reply_t select_reply;
|
||||
};
|
||||
|
||||
struct recv_q {
|
||||
|
|
@ -63,6 +66,23 @@ struct recv_q {
|
|||
SOCK_FLG_SEL_ERROR); \
|
||||
} while (0)
|
||||
|
||||
struct sock_req {
|
||||
enum {
|
||||
SOCK_REQ_READ,
|
||||
SOCK_REQ_WRITE,
|
||||
SOCK_REQ_IOCTL
|
||||
} type;
|
||||
devminor_t minor;
|
||||
endpoint_t endpt;
|
||||
cp_grant_id_t grant;
|
||||
union {
|
||||
size_t size; /* for SOCK_REQ_READ, SOCK_REQ_WRITE */
|
||||
unsigned long req; /* for SOCK_REQ_IOCTL */
|
||||
};
|
||||
int flags;
|
||||
cdev_id_t id;
|
||||
};
|
||||
|
||||
struct socket {
|
||||
int type;
|
||||
u32_t flags;
|
||||
|
|
@ -71,9 +91,7 @@ struct socket {
|
|||
struct sock_ops * ops;
|
||||
void * buf;
|
||||
size_t buf_size;
|
||||
message mess; /* store the message which initiated the
|
||||
last operation on this socket in case
|
||||
we have to suspend the operation */
|
||||
struct sock_req req;
|
||||
void * shm;
|
||||
size_t shm_size;
|
||||
endpoint_t select_ep;
|
||||
|
|
@ -87,7 +105,7 @@ struct socket {
|
|||
* Each component needs to provide a method how to initially open a socket.
|
||||
* The rest is handled byt the socket library.
|
||||
*/
|
||||
void socket_open(message * m);
|
||||
int socket_open(devminor_t minor);
|
||||
|
||||
#define get_sock_num(x) ((long int) ((x) - socket))
|
||||
#define is_valid_sock_num(x) (x < MAX_SOCKETS)
|
||||
|
|
@ -100,19 +118,13 @@ void socket_open(message * m);
|
|||
|
||||
extern struct socket socket[MAX_SOCKETS];
|
||||
|
||||
void socket_request(message * m);
|
||||
void socket_request(message * m, int ipc_status);
|
||||
void mq_process(void);
|
||||
|
||||
|
||||
struct socket * get_unused_sock(void);
|
||||
struct socket * get_nic_sock(unsigned dev);
|
||||
|
||||
void send_reply(message * m, int status);
|
||||
void send_reply_open(message * m, int status);
|
||||
void send_reply_close(message * m, int status);
|
||||
void sock_reply(struct socket * sock, int status);
|
||||
void sock_reply_close(struct socket * sock, int status);
|
||||
void sock_reply_select(struct socket * sock, unsigned selops);
|
||||
void send_req_reply(struct sock_req * req, int status);
|
||||
|
||||
typedef void (* recv_data_free_fn)(void *);
|
||||
|
||||
|
|
@ -139,10 +151,8 @@ static inline void * debug_malloc(size_t s)
|
|||
free(x); \
|
||||
} while(0)
|
||||
|
||||
void generic_op_select(struct socket * sock, message * m);
|
||||
void generic_op_select_reply(struct socket * sock, message * m);
|
||||
|
||||
int mq_enqueue(message * m);
|
||||
int generic_op_select(struct socket * sock, unsigned int sel);
|
||||
int generic_op_select_reply(struct socket * sock);
|
||||
|
||||
/* a function thr user has to provide to reply to the posix server */
|
||||
void posix_reply(endpoint_t ep, message * m);
|
||||
|
|
|
|||
|
|
@ -17,4 +17,6 @@
|
|||
|
||||
#define _PATH_RAMDISK "/dev/ram"
|
||||
|
||||
#define _PATH_DRIVERS "/usr/sbin"
|
||||
|
||||
#endif /* _MINIX_PATHS_H_ */
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@
|
|||
#define FSTATE_LOCK 'L'
|
||||
#define FSTATE_POPEN 'O'
|
||||
#define FSTATE_SELECT 'S'
|
||||
#define FSTATE_DOPEN 'D'
|
||||
#define FSTATE_TASK 'T'
|
||||
#define FSTATE_UNKNOWN '?'
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ int getsysinfo(endpoint_t who, int what, void *where, size_t size);
|
|||
#define SI_DATA_STORE 5 /* get copy of data store mappings */
|
||||
#define SI_CALL_STATS 9 /* system call statistics */
|
||||
#define SI_PROCPUB_TAB 11 /* copy of public entries of process table */
|
||||
#define SI_VMNT_TAB 12 /* get vmnt table */
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -69,8 +69,6 @@ int sys_vmctl_enable_paging(void * data);
|
|||
int sys_readbios(phys_bytes address, void *buf, size_t size);
|
||||
int sys_settime(int now, clockid_t clk_id, time_t sec, long nsec);
|
||||
int sys_stime(time_t boottime);
|
||||
int sys_sysctl(int ctl, char *arg1, int arg2);
|
||||
int sys_sysctl_stacktrace(endpoint_t who);
|
||||
int sys_vmctl_get_mapping(int index, phys_bytes *addr, phys_bytes *len,
|
||||
int *flags);
|
||||
int sys_vmctl_reply_mapping(int index, vir_bytes addr);
|
||||
|
|
@ -159,7 +157,16 @@ int sys_umap_data_fb(endpoint_t proc_ep, vir_bytes vir_addr, vir_bytes
|
|||
int sys_umap_remote(endpoint_t proc_ep, endpoint_t grantee, int seg,
|
||||
vir_bytes vir_addr, vir_bytes bytes, phys_bytes *phys_addr);
|
||||
|
||||
int send_taskreply(endpoint_t who, endpoint_t endpoint, int status);
|
||||
/* Shorthands for sys_diagctl() system call. */
|
||||
#define sys_diagctl_diag(buf,len) \
|
||||
sys_diagctl(DIAGCTL_CODE_DIAG, buf, len)
|
||||
#define sys_diagctl_stacktrace(ep) \
|
||||
sys_diagctl(DIAGCTL_CODE_STACKTRACE, NULL, ep)
|
||||
#define sys_diagctl_register() \
|
||||
sys_diagctl(DIAGCTL_CODE_REGISTER, NULL, 0)
|
||||
#define sys_diagctl_unregister() \
|
||||
sys_diagctl(DIAGCTL_CODE_UNREGISTER, NULL, 0)
|
||||
int sys_diagctl(int ctl, char *arg1, int arg2);
|
||||
|
||||
/* Shorthands for sys_getinfo() system call. */
|
||||
#define sys_getkinfo(dst) sys_getinfo(GET_KINFO, dst, 0,0,0)
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
|
||||
#ifndef _MINIX_TTY_H
|
||||
#define _MINIX_TTY_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#define TTYMAGIC 0xb105
|
||||
|
||||
/* A struct that the tty driver can use to pass values to the boot monitor.
|
||||
* Currently only the value of the origin of the first vty (console), so the
|
||||
* boot monitor can properly display it when panicing (tty isn't scheduled
|
||||
* to switch to the first vty). It's written at the end of video memory
|
||||
* (video memory base + video memory size - sizeof(struct boot_tty_info).
|
||||
*/
|
||||
|
||||
struct boot_tty_info {
|
||||
u16_t reserved[30]; /* reserved, set to 0 */
|
||||
u16_t consorigin; /* origin in video memory of console */
|
||||
u16_t conscursor; /* position of cursor of console */
|
||||
u16_t flags; /* flags indicating which fields are valid */
|
||||
u16_t magic; /* magic number indicating struct is valid */
|
||||
};
|
||||
|
||||
#define BTIF_CONSORIGIN 0x01 /* consorigin is set */
|
||||
#define BTIF_CONSCURSOR 0x02 /* conscursor is set */
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ typedef struct {
|
|||
#define REQ_INHIBREAD (VFS_BASE + 7)
|
||||
#define REQ_STAT (VFS_BASE + 8)
|
||||
#define REQ_UTIME (VFS_BASE + 9)
|
||||
#define REQ_FSTATFS (VFS_BASE + 10)
|
||||
#define REQ_STATVFS (VFS_BASE + 10)
|
||||
#define REQ_BREAD (VFS_BASE + 11)
|
||||
#define REQ_BWRITE (VFS_BASE + 12)
|
||||
#define REQ_UNLINK (VFS_BASE + 13)
|
||||
|
|
@ -115,11 +115,10 @@ typedef struct {
|
|||
#define REQ_NEWNODE (VFS_BASE + 29)
|
||||
#define REQ_RDLINK (VFS_BASE + 30)
|
||||
#define REQ_GETDENTS (VFS_BASE + 31)
|
||||
#define REQ_STATVFS (VFS_BASE + 32)
|
||||
#define REQ_PEEK (VFS_BASE + 33)
|
||||
#define REQ_BPEEK (VFS_BASE + 34)
|
||||
#define REQ_PEEK (VFS_BASE + 32)
|
||||
#define REQ_BPEEK (VFS_BASE + 33)
|
||||
|
||||
#define NREQS 35
|
||||
#define NREQS 34
|
||||
|
||||
#define IS_VFS_RQ(type) (((type) & ~0xff) == VFS_BASE)
|
||||
|
||||
|
|
@ -127,19 +126,5 @@ typedef struct {
|
|||
#define TRNS_ADD_ID(t,id) (((t) << 16) | ((id) & 0xFFFF))
|
||||
#define TRNS_DEL_ID(t) ((short)((t) >> 16))
|
||||
|
||||
#define PFS_BASE (VFS_BASE + 100)
|
||||
|
||||
#define PFS_REQ_CHECK_PERMS (PFS_BASE + 1)
|
||||
#define PFS_REQ_VERIFY_FD (PFS_BASE + 2)
|
||||
#define PFS_REQ_SET_FILP (PFS_BASE + 3)
|
||||
#define PFS_REQ_COPY_FILP (PFS_BASE + 4)
|
||||
#define PFS_REQ_PUT_FILP (PFS_BASE + 5)
|
||||
#define PFS_REQ_CANCEL_FD (PFS_BASE + 6)
|
||||
|
||||
#define PFS_NREQS 7
|
||||
|
||||
#define IS_PFS_VFS_RQ(type) (type >= PFS_BASE && \
|
||||
type < (PFS_BASE + PFS_NREQS))
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ int vm_set_cacheblock(void *block, u32_t dev, u64_t dev_offset,
|
|||
void *vm_map_cacheblock(u32_t dev, u64_t dev_offset,
|
||||
u64_t ino, u64_t ino_offset, u32_t *flags, int blocksize);
|
||||
|
||||
int vm_clear_cache(u32_t dev);
|
||||
|
||||
/* flags for vm cache functions */
|
||||
#define VMMC_FLAGS_LOCKED 0x01 /* someone is updating the flags; don't read/write */
|
||||
#define VMMC_DIRTY 0x02 /* dirty buffer and it may not be evicted */
|
||||
|
|
|
|||
|
|
@ -271,12 +271,10 @@ int cgetustr(char *, const char *, char **);
|
|||
void csetexpandtc(int);
|
||||
|
||||
int daemon(int, int);
|
||||
#ifndef __minix
|
||||
int devname_r(dev_t, mode_t, char *, size_t);
|
||||
#ifndef __LIBC12_SOURCE__
|
||||
__aconst char *devname(dev_t, mode_t) __RENAME(__devname50);
|
||||
#endif
|
||||
#endif /* !__minix */
|
||||
|
||||
#define HN_DECIMAL 0x01
|
||||
#define HN_NOSPACE 0x02
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ enum {
|
|||
};
|
||||
|
||||
/* The I/O control requests. */
|
||||
#define FBDCADDRULE _IOW('F', 1, struct fbd_rule) /* add a rule */
|
||||
#define FBDCDELRULE _IOW('F', 2, fbd_rulenum_t) /* delete a rule */
|
||||
#define FBDCGETRULE _IORW('F', 3, struct fbd_rule) /* retrieve a rule */
|
||||
#define FBDCADDRULE _IOW('B', 1, struct fbd_rule) /* add a rule */
|
||||
#define FBDCDELRULE _IOW('B', 2, fbd_rulenum_t) /* delete a rule */
|
||||
#define FBDCGETRULE _IORW('B', 3, struct fbd_rule) /* retrieve a rule */
|
||||
|
||||
#endif /* _S_I_FBD_H */
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user