2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Unix filedescriptor/socket IO
10 #define timeval sys_timeval /* We don't want the unix timeval to interfere with the AROS one */
11 #include <sys/types.h>
15 #include <sys/ioctl.h>
24 #include <aros/debug.h>
26 #define __OOP_NOATTRBASES__
28 #include <exec/types.h>
29 #include <exec/lists.h>
30 #include <exec/interrupts.h>
31 #include <exec/execbase.h>
32 #include <exec/semaphores.h>
33 #include <exec/memory.h>
34 #include <exec/resident.h>
35 #include <exec/tasks.h>
36 #include <exec/ports.h>
37 #include <exec/nodes.h>
38 #include <intuition/intuition.h>
39 #include <utility/tagitem.h>
40 #include <utility/hooks.h>
41 #include <hidd/unixio.h>
42 #include <aros/asmcall.h>
43 #include <aros/symbolsets.h>
46 #include <proto/exec.h>
47 #include <proto/hostlib.h>
48 #include <proto/intuition.h>
49 #include <proto/kernel.h>
50 #include <proto/oop.h>
51 #include <proto/utility.h>
52 #include <proto/alib.h>
54 #include <devices/timer.h>
58 #include LC_LIBDEFS_FILE
60 #include <aros/asmcall.h>
62 /*****************************************************************************************
71 unixio.hidd is a simple driver for host-side I/O on UNIX system. Its primary
72 purpose is to handle non-blocking I/O on AROS task level. Also it provides
73 common file access operations (open, close, read, write and ioctl) in order
74 to avoid code duplication.
76 I/O operations you perform must never block. The whole AROS with all its tasks
77 is just one process from host OS' point of view, so blocking operation would
78 halt all the system. In order to avoid this you need to make sure that the
79 file descriptor is actually ready to perform I/O. If this is not the case,
80 your task needs to wait until file descriptor becomes available. unixio.hidd
81 offers a simple way of doing it by adding an interrupt handler to the file
82 descriptor using moHidd_UnixIO_AddInterrupt method. The interrupt handler
83 will be called whenever SIGIO arrives from the specified descriptor and specified
84 conditions are met. You do not need to explicitly enable asynchronous I/O
85 on the file descriptor, unixio.hidd takes care about all this itself.
87 There's also a convenience moHidd_UnixIO_Wait method. It allows you to simulate
88 a normal blocking I/O in a simple way.
90 Starting from v42 unixio.hidd is a singletone. This means that all calls to
91 OOP_NewObject() will actually return the same object which is never really
92 disposed. This object pointer can be freely transferred between tasks. It's
93 not necessary t call OOP_DisposeObject() on it. It is safe, but will do nothing.
94 Usage counter is maintained by OpenLibrary()/CloseLibrary() calls.
96 Remember that all values (like file mode flags and errno values) are host-specific!
97 Different hosts may use different values, and even different structure layouts
98 (especially this affects ioctl). When opening unixio.hidd it is adviced to check
99 that host OS matches what is expected (what your client program/driver/whatever
100 is compiled for). Use aoHidd_UnixIO_Architecture attribute for this.
102 *****************************************************************************************/
104 static int poll_fd(int fd
, int req_mode
, struct unixio_base
*ud
)
106 struct pollfd pfd
= {fd
, 0, 0};
110 if (req_mode
& vHidd_UnixIO_Read
)
111 pfd
.events
|= POLLIN
;
112 if (req_mode
& vHidd_UnixIO_Write
)
113 pfd
.events
|= POLLOUT
;
115 res
= ud
->SysIFace
->poll(&pfd
, 1, 0);
120 if (pfd
.revents
& POLLIN
)
121 mode
|= vHidd_UnixIO_Read
;
122 if (pfd
.revents
& POLLOUT
)
123 mode
|= vHidd_UnixIO_Write
;
124 if (pfd
.revents
& (POLLERR
|POLLHUP
))
125 mode
|= vHidd_UnixIO_Error
;
133 static void SigIO_IntServer(struct unixio_base
*ud
, void *unused
)
135 struct uioInterrupt
*intnode
;
137 /* Walk through the list of installed handlers and de-multiplex our SIGIO */
138 for (intnode
= (struct uioInterrupt
*)ud
->intList
.mlh_Head
; intnode
->Node
.mln_Succ
;
139 intnode
= (struct uioInterrupt
*)intnode
->Node
.mln_Succ
)
141 int mode
= poll_fd(intnode
->fd
, intnode
->mode
, ud
);
145 D(bug("[UnixIO] Events 0x%02X for fd %d\n", mode
, intnode
->fd
));
147 intnode
->handler(intnode
->fd
, mode
, intnode
->handlerData
);
152 static void WaitIntHandler(int fd
, int mode
, void *data
)
154 struct UnixIO_Waiter
*w
= data
;
155 Signal(w
->task
, 1 << w
->signal
);
158 static BOOL
CheckArch(struct unixio_base
*data
, STRPTR Component
, STRPTR MyArch
)
160 STRPTR arg
[3] = {Component
, MyArch
, data
->SystemArch
};
162 D(bug("[UnixIO] My architecture: %s, kernel architecture: %s\n", arg
[1], arg
[2]));
164 if (strcmp(arg
[1], arg
[2]))
166 struct IntuitionBase
*IntuitionBase
;
168 IntuitionBase
= (struct IntuitionBase
*)OpenLibrary("intuition.library", 36);
171 struct EasyStruct es
= {
172 sizeof (struct EasyStruct
),
174 "Incompatible architecture",
175 "Used version of %s is built for use\n"
176 "with %s architecture, but your\n"
177 "system architecture is %s.",
181 EasyRequestArgs(NULL
, &es
, NULL
, (RAWARG
)arg
);
183 CloseLibrary(&IntuitionBase
->LibNode
);
188 D(bug("[UnixIO] Architecture check done\n"));
192 #define HostLibBase data->HostLibBase
193 #define KernelBase data->KernelBase
195 #undef HiddUnixIOAttrBase
196 #define HiddUnixIOAttrBase data->UnixIOAB
198 /*****************************************************************************************
210 Specifiers opener name for architecture check routine.
213 This attribute's sole purpose is to be presented to the user in an error requester
214 if the architecture check fails. For example if you specify "tap.device" here,
215 the user will see a requester telling that "This version of tap.device is built
216 for XXX architecture, while current system architecture is YYY".
218 If this attribute is not specified, but architecture check is requested using
219 aoHidd_UnixIO_Architecture, current task's name will be used. This can be not
220 always approptiate, so it's adviced to always specify your driver or program
228 aoHidd_UnixIO_Architecture
232 *****************************************************************************************/
233 /*****************************************************************************************
236 aoHidd_UnixIO_Architecture
245 Specifiers architecture name to match against current system's architecture.
246 Architecture name needs to be supplied in the form "arch-cpu", for example
247 "linux-ppc" or "darwin-i386". Usually this comes from a definition when
248 you compile your module.
251 This attribute allows you to ensure that your module is running on the same
252 architecture it was compiled for. This is needed because unixio.hidd by its
253 nature works with host OS structures and values (especially ioctl operation).
254 Different host OSes (for example Linux and Darwin) are not binary compatible
255 even on the same CPU. This is why the architecture check is generally needed,
256 especially for disk-based components.
258 It is adviced to specify your module name using aoHidd_UnixIO_Opener. This needed
259 in order to display the correct name to the user if the check fails, so the user
260 will see what module causes the error.
264 struct TagItem tags = {
265 {aHidd_UnixIO_Opener, "tap.device"},
266 {aHidd_UnixIO_Architecture, "linux-i386"},
269 uio = OOP_NewObject(CLID_Hidd_UnixIO, tags);
270 // If uio == NULL, the system you're running on is not linux-i386. The error
271 // requester has been already presented to the user.
280 *****************************************************************************************/
281 /* The following are methods of the UnixIO HIDD class. */
283 /********************
285 ********************/
286 OOP_Object
*UXIO__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
288 struct unixio_base
*data
= UD(cl
);
291 EnterFunc(bug("UnixIO::New(cl=%s)\n", cl
->ClassNode
.ln_Name
));
293 archName
= (STRPTR
)GetTagData(aHidd_UnixIO_Architecture
, 0, msg
->attrList
);
296 struct Task
*t
= FindTask(NULL
);
297 STRPTR moduleName
= (STRPTR
)GetTagData(aHidd_UnixIO_Opener
, (IPTR
)t
->tc_Node
.ln_Name
, msg
->attrList
);
299 if (!CheckArch(data
, moduleName
, archName
))
303 /* We are a true singletone */
304 ObtainSemaphore(&data
->lock
);
308 D(bug("[UnixIO] Creating object\n"));
309 data
->obj
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
312 ReleaseSemaphore(&data
->lock
);
314 ReturnPtr("UnixIO::New", OOP_Object
*, data
->obj
);
317 /***********************
318 ** UnixIO::Dispose() **
319 ***********************/
320 void UXIO__Root__Dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
324 * We can't just omit this method because in this case Dispose() will be called
325 * on our superclass, which is not what we want.
329 /*****************************************************************************************
335 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_ *msg);
337 IPTR Hidd_UnixIO_Wait(OOP_Object *obj, ULONG fd, ULONG mode);
343 Wait for an event on the file descriptor.
346 obj - A pointer to a UnixIO object
347 fd - A file descriptor to wait on
348 mode - A combination of two flags:
349 - vHidd_UnixIO_Read - to request waiting until read is permitted
350 - vHidd_UnixIO_Write - to request waiting until write is permitted
353 0 in case of success or UNIX errno value in case if the operation failed.
367 *****************************************************************************************/
368 IPTR
UXIO__Hidd_UnixIO__Wait(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_UnixIO_Wait
*msg
)
372 struct uioInterrupt myInt
;
373 struct UnixIO_Waiter w
;
375 /* Check if the fd is already ready. In this case we don't need to wait for anything. */
376 mode
= Hidd_UnixIO_Poll(o
, msg
->FD
, msg
->Mode
, &retval
);
378 return (mode
== -1) ? retval
: 0;
380 w
.signal
= AllocSignal(-1);
384 w
.task
= FindTask(NULL
);
387 myInt
.mode
= msg
->Mode
;
388 myInt
.handler
= WaitIntHandler
;
389 myInt
.handlerData
= &w
;
391 D(bug("[UnixIO] Adding interrupt 0x%P\n", &myInt
));
393 retval
= Hidd_UnixIO_AddInterrupt(o
, &myInt
);
394 D(bug("[UnixIO] Result: %d\n", retval
));
398 D(bug("[UnixIO] Waiting for signal...\n"));
400 Hidd_UnixIO_RemInterrupt(o
, &myInt
);
403 FreeSignal(w
.signal
);
408 /*****************************************************************************************
411 moHidd_UnixIO_OpenFile
414 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_OpenFile *msg);
416 int Hidd_UnixIO_OpenFile (OOP_Object *obj, const char *filename, int flags, int mode, int *errno_ptr);
422 Open a UNIX file descriptor
425 obj - An pointer to a UnixIO object
426 filename - File name to open. File name should meet host OS conventions.
427 flags - Flags specifying open mode. These are the same flags as for
428 open() C function. Note that this value is passed directly to
429 the host OS, and its definition can differ from AROS one.
430 errno_ptr - An optional pointer to a location where error code (value of
431 UNIX errno variable) will be written
434 A number of the opened file descriptor or -1 for an error.
443 moHidd_UnixIO_CloseFile
449 *****************************************************************************************/
451 APTR
UXIO__Hidd_UnixIO__OpenFile(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_UnixIO_OpenFile
*msg
)
453 struct unixio_base
*data
= UD(cl
);
456 D(bug("[UnixIO] OpenFile(%s, 0x%04X, %o)\n", msg
->FileName
, msg
->Flags
, msg
->Mode
));
460 retval
= (APTR
)(unsigned long)data
->SysIFace
->open(msg
->FileName
, (int)msg
->Flags
, (int)msg
->Mode
);
464 *msg
->ErrNoPtr
= *data
->uio_Public
.uio_ErrnoPtr
;
468 D(bug("[UnixIO] FD is %d, errno is %d\n", retval
, *data
->uio_Public
.uio_ErrnoPtr
));
473 /*****************************************************************************************
476 moHidd_UnixIO_CloseFile
479 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_CloseFile *msg);
481 int Hidd_UnixIO_CloseFile (OOP_Object *obj, int fd, int *errno_ptr);
487 Close a UNIX file descriptor.
490 obj - A pointer to a UnixIO object.
491 fd - A file descriptor to close.
492 errno_ptr - An optional pointer to a location where error code (a value of UNIX
493 errno variable) will be written.
496 0 in case of success and -1 on failure.
499 Despite there's no return value, error code still can be set.
506 moHidd_UnixIO_OpenFile
512 *****************************************************************************************/
513 int UXIO__Hidd_UnixIO__CloseFile(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_UnixIO_CloseFile
*msg
)
515 struct unixio_base
*data
= UD(cl
);
522 ret
= data
->SysIFace
->close((long)msg
->FD
);
526 *msg
->ErrNoPtr
= *data
->uio_Public
.uio_ErrnoPtr
;
534 /*****************************************************************************************
537 moHidd_UnixIO_ReadFile
540 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_ReadFile *msg);
542 int Hidd_UnixIO_ReadFile(OOP_Object *obj, int fd, void *buffer, int count, int *errno_ptr);
548 Read data from a UNIX file descriptor.
551 obj - A pointer to a UnixIO object.
552 fd - A file descriptor to read from.
553 buffer - A pointer to a buffer for data.
554 count - Number of bytes to read.
555 errno_ptr - An optional pointer to a location where error code (a value of UNIX
556 errno variable) will be written.
559 Number of bytes actually read or -1 if error happened.
562 If there's no errno pointer supplied read operation will be automatically repeated if one
563 of EINTR or EAGAIN error happens. If you supplied valid own errno_ptr you should be ready
564 to handle these conditions yourself.
566 This method can be called from within interrupts.
573 moHidd_UnixIO_WriteFile
579 *****************************************************************************************/
580 IPTR
UXIO__Hidd_UnixIO__ReadFile(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_UnixIO_ReadFile
*msg
)
582 struct unixio_base
*data
= UD(cl
);
584 volatile int err
= EINVAL
;
588 int user
= !KrnIsSuper();
595 retval
= data
->SysIFace
->read((long)msg
->FD
, (void *)msg
->Buffer
, (size_t)msg
->Count
);
598 err
= *data
->uio_Public
.uio_ErrnoPtr
;
599 D(kprintf(" UXIO__Hidd_UnixIO__ReadFile: retval %d errno %d buff %x count %d\n", retval
, err
, msg
->Buffer
, msg
->Count
));
604 } while((err
== EINTR
) || (err
== EAGAIN
));
611 *msg
->ErrNoPtr
= err
;
613 D(if (retval
== -1) kprintf("UXIO__Hidd_UnixIO__ReadFile: errno %d buff %x count %d\n", err
, msg
->Buffer
, msg
->Count
));
618 /*****************************************************************************************
621 moHidd_UnixIO_WriteFile
624 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_WriteFile *msg);
626 int Hidd_UnixIO_WriteFile(OOP_Object *obj, int fd, void *buffer, int count, int *errno_ptr);
632 Write data to a UNIX file descriptor.
635 obj - A pointer to a UnixIO object.
636 fd - A file descriptor to write to.
637 buffer - A pointer to a buffer containing data.
638 count - Number of bytes to write.
639 errno_ptr - An optional pointer to a location where error code (a value of UNIX
640 errno variable) will be written.
643 Number of bytes actually written or -1 if error happened.
646 If there's no errno pointer supplied read operation will be automatically repeated if one
647 of EINTR or EAGAIN error happens. If you supplied valid own errno_ptr you should be ready
648 to handle these conditions yourself.
650 This method can be called from within interrupts.
657 moHidd_UnixIO_ReadFile
663 *****************************************************************************************/
664 IPTR
UXIO__Hidd_UnixIO__WriteFile(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_UnixIO_WriteFile
*msg
)
666 struct unixio_base
*data
= UD(cl
);
668 volatile int err
= EINVAL
;
672 int user
= !KrnIsSuper();
679 retval
= data
->SysIFace
->write((long)msg
->FD
, (const void *)msg
->Buffer
, (size_t)msg
->Count
);
682 err
= *data
->uio_Public
.uio_ErrnoPtr
;
683 D(kprintf(" UXIO__Hidd_UnixIO__WriteFile: retval %d errno %d buff %x count %d\n", retval
, err
, msg
->Buffer
, msg
->Count
));
688 } while((retval
< 1) && ((err
== EINTR
) || (err
== EAGAIN
) || (err
== 0)));
695 *msg
->ErrNoPtr
= err
;
697 D(if (retval
== -1) kprintf("UXIO__Hidd_UnixIO__WriteFile: errno %d buff %x count %d\n", err
, msg
->Buffer
, msg
->Count
));
702 /*****************************************************************************************
705 moHidd_UnixIO_IOControlFile
708 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_IOControlFile *msg);
710 int Hidd_UnixIO_IOControlFile(OOP_Object *obj, int fd, int request, void *param, int *errno_ptr);
716 Perform a special operation (ioctl) on a UNIX file descriptor.
719 obj - A pointer to a UnixIO object.
720 fd - A file descriptor to operate on.
721 request - A device-specific operation code.
722 param - A pointer to a request-specific parameter block.
723 errno_ptr - An optional pointer to a location where error code (a value of UNIX
724 errno variable) will be written.
727 Operation-specific value (actually a return value of ioctl() function called).
730 This method can be called from within interrupts.
742 *****************************************************************************************/
743 IPTR
UXIO__Hidd_UnixIO__IOControlFile(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_UnixIO_IOControlFile
*msg
)
745 struct unixio_base
*data
= UD(cl
);
751 int user
= !KrnIsSuper();
756 retval
= data
->SysIFace
->ioctl((long)msg
->FD
, (int)msg
->Request
, msg
->Param
);
759 err
= *data
->uio_Public
.uio_ErrnoPtr
;
766 *msg
->ErrNoPtr
= err
;
771 /*****************************************************************************************
774 moHidd_UnixIO_AddInterrupt
777 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_AddInterrupt *msg);
779 int Hidd_UnixIO_AddInterrupt(OOP_Object *obj, struct uioInterrupt *interrupt);
785 Install a filedescriptor-specific event interrupt handler
788 obj - An pointer to a UnixIO object
789 interrupt - A pointer to an interrupt descriptor structure initialized as follows:
790 fd - Number of file descriptor to watch
791 mode - one or more of mode flags
792 handler - A pointer to a handler routine.
793 handlerData - User-specified data for the interrupt handler
795 The interrupt handler routine will be called using C calling convention:
797 void handler(int fd, int mode, void *data)
800 fd - File descriptor number
801 mode - Flags reflecting set of occured events
802 data - User data (specified in handlerData member of uioInterrupt structure)
805 Zero if interrupt was succesfully installed and UNIX errno value if there was en error
806 during setting up the filedescriptor.
815 moHidd_UnixIO_RemInterrupt
821 *****************************************************************************************/
822 int UXIO__Hidd_UnixIO__AddInterrupt(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_UnixIO_AddInterrupt
*msg
)
824 struct unixio_base
*data
= UD(cl
);
829 AddTail((struct List
*)&data
->intList
, (struct Node
*)msg
->Int
);
832 /* Now own the filedescriptor and enable SIGIO on it */
835 res
= data
->SysIFace
->fcntl(msg
->Int
->fd
, F_SETOWN
, data
->aros_PID
);
840 res
= data
->SysIFace
->fcntl(msg
->Int
->fd
, F_GETFL
);
842 res
= data
->SysIFace
->fcntl(msg
->Int
->fd
, F_SETFL
, res
|O_ASYNC
);
845 err
= *data
->uio_Public
.uio_ErrnoPtr
;
852 /* Remove the interrupt if something went wrong */
853 Hidd_UnixIO_RemInterrupt(o
, msg
->Int
);
858 /*****************************************************************************************
861 moHidd_UnixIO_RemInterrupt
864 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_RemInterrupt *msg);
866 void Hidd_UnixIO_RemInterrupt(OOP_Object *obj, struct uioInterrupt *interrupt);
872 Remove previously installed file descriptor event interrupt structure
875 obj - An pointer to a UnixIO object
876 interrupt - A pointer to a previously installed interrupt descriptor structure
888 moHidd_UnixIO_AddInterrupt
894 *****************************************************************************************/
895 void UXIO__Hidd_UnixIO__RemInterrupt(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_UnixIO_RemInterrupt
*msg
)
899 Remove((struct Node
*)msg
->Int
);
903 * We do not disable O_ASYNC because theoretically we can have more
904 * than one interrupt on a single fd.
905 * Anyway typically removing interrupt handler means the fd is not
906 * going to be used any more and will be closed soon.
910 /*****************************************************************************************
916 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_Poll *msg);
918 int Hidd_UnixIO_Poll(OOP_Object *obj, int fd, int mode, int *errno_ptr);
924 Check current status of UNIX file descriptor or -1 if an error occured.
927 obj - A pointer to a UnixIO object.
928 fd - A file descriptor to check.
929 mode - Mask of modes we are interested in.
930 errno_ptr - An optional pointer to a location where error code (a value of UNIX
931 errno variable) will be written.
934 Current set of filedescriptor modes.
937 This method can be called from within interrupts.
949 *****************************************************************************************/
950 ULONG
UXIO__Hidd_UnixIO__Poll(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_UnixIO_Poll
*msg
)
952 struct unixio_base
*data
= UD(cl
);
953 int user
= !KrnIsSuper();
959 ret
= poll_fd((int)(IPTR
)msg
->FD
, msg
->Mode
, data
);
961 *msg
->ErrNoPtr
= *data
->uio_Public
.uio_ErrnoPtr
;
969 /*****************************************************************************************
972 moHidd_UnixIO_MemoryMap
975 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_MemoryMap *msg);
977 int Hidd_UnixIO_MemoryMap(OOP_Object *obj, OOP_Object *o, void *addr, int len, int prot, int flags, int fd, int offset, int *errno_ptr);
983 Maps address into file descriptor.
986 obj - A pointer to a UnixIO object.
987 fd - A file descriptor to check.
988 errno_ptr - An optional pointer to a location where error code (a value of UNIX
989 errno variable) will be written.
992 Actuall mapping address or MAP_FAILED for errors.
995 This method can be called from within interrupts.
1007 *****************************************************************************************/
1008 APTR
UXIO__Hidd_UnixIO__MemoryMap(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_UnixIO_MemoryMap
*msg
)
1010 struct unixio_base
*data
= UD(cl
);
1011 int user
= !KrnIsSuper();
1017 ret
= data
->SysIFace
->mmap(msg
->Address
, msg
->Length
, msg
->Prot
, msg
->Flags
, (int)(IPTR
)msg
->FD
, msg
->Offset
);
1019 *msg
->ErrNoPtr
= *data
->uio_Public
.uio_ErrnoPtr
;
1027 /*****************************************************************************************
1030 moHidd_UnixIO_MemoryUnMap
1033 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_MemoryUnMap *msg);
1035 int Hidd_UnixIO_MemoryUnMap(OOP_Object *obj, OOP_Object *o, void *addr, int len, int *errno_ptr);
1044 obj - A pointer to a UnixIO object.
1045 errno_ptr - An optional pointer to a location where error code (a value of UNIX
1046 errno variable) will be written.
1049 0 for success, -1 for failure
1052 This method can be called from within interrupts.
1064 *****************************************************************************************/
1065 IPTR
UXIO__Hidd_UnixIO__MemoryUnMap(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_UnixIO_MemoryUnMap
*msg
)
1067 struct unixio_base
*data
= UD(cl
);
1068 int user
= !KrnIsSuper();
1074 ret
= data
->SysIFace
->munmap(msg
->Address
, msg
->Length
);
1076 *msg
->ErrNoPtr
= *data
->uio_Public
.uio_ErrnoPtr
;
1084 /* This is the initialisation code for the HIDD class itself. */
1086 static const char *libc_symbols
[] =
1096 #ifdef HOST_OS_linux
1099 #ifdef HOST_OS_android
1116 #define KernelBase LIBBASE->KernelBase
1117 #define HostLibBase LIBBASE->HostLibBase
1119 static int UXIO_Init(LIBBASETYPEPTR LIBBASE
)
1123 D(bug("[UnixIO] Init\n"));
1125 KernelBase
= OpenResource("kernel.resource");
1129 HostLibBase
= OpenResource("hostlib.resource");
1133 LIBBASE
->SystemArch
= (STRPTR
)KrnGetSystemAttr(KATTR_Architecture
);
1134 if (!LIBBASE
->SystemArch
)
1137 if (!CheckArch(LIBBASE
, "unixio.hidd", AROS_ARCHITECTURE
))
1140 LIBBASE
->UnixIOAB
= OOP_ObtainAttrBase(IID_Hidd_UnixIO
);
1141 if (!LIBBASE
->UnixIOAB
)
1144 LIBBASE
->uio_Public
.uio_LibcHandle
= HostLib_Open(LIBC_NAME
, NULL
);
1145 if (!LIBBASE
->uio_Public
.uio_LibcHandle
)
1148 LIBBASE
->SysIFace
= (struct LibCInterface
*)HostLib_GetInterface(LIBBASE
->uio_Public
.uio_LibcHandle
, libc_symbols
, &i
);
1149 if ((!LIBBASE
->SysIFace
) || i
)
1152 LIBBASE
->irqHandle
= KrnAddIRQHandler(SIGIO
, SigIO_IntServer
, LIBBASE
, NULL
);
1153 if (!LIBBASE
->irqHandle
)
1156 NewList((struct List
*)&LIBBASE
->intList
);
1157 InitSemaphore(&LIBBASE
->lock
);
1159 LIBBASE
->uio_Public
.uio_ErrnoPtr
= LIBBASE
->SysIFace
->__error();
1161 LIBBASE
->aros_PID
= LIBBASE
->SysIFace
->getpid();
1167 static int UXIO_Cleanup(struct unixio_base
*LIBBASE
)
1169 D(bug("[UnixIO] Expunging\n"));
1171 if ((!KernelBase
) || (!HostLibBase
))
1174 if (LIBBASE
->irqHandle
)
1175 KrnRemIRQHandler(LIBBASE
->irqHandle
);
1177 if (LIBBASE
->SysIFace
)
1178 HostLib_DropInterface ((APTR
*)LIBBASE
->SysIFace
);
1180 if (LIBBASE
->uio_Public
.uio_LibcHandle
)
1181 HostLib_Close(LIBBASE
->uio_Public
.uio_LibcHandle
, NULL
);
1183 if (LIBBASE
->UnixIOAB
)
1184 OOP_ReleaseAttrBase(IID_Hidd_UnixIO
);
1189 /* The singleton gets really disposed only when we expunge its library */
1190 static int UXIO_Dispose(struct unixio_base
*LIBBASE
)
1194 OOP_MethodID mid
= OOP_GetMethodID(IID_Root
, moRoot_Dispose
);
1196 D(bug("[UnixIO] Disposing object\n"));
1198 OOP_DoSuperMethod(LIBBASE
->uio_unixioclass
, LIBBASE
->obj
, &mid
);
1199 LIBBASE
->obj
= NULL
;
1205 ADD2INITLIB(UXIO_Init
, 0)
1206 ADD2EXPUNGELIB(UXIO_Cleanup
, 0)
1207 ADD2SET(UXIO_Dispose
, CLASSESEXPUNGE
, 0)