/* IOMain.c, Copyright (c) by George Fankhauser, Swiss Federal Institute of Technology, Computer Engineering and Networks Laboratory. TOPSY -- A Teachable Operating System. Implementation of a tiny and simple micro kernel for teaching purposes. For further information, please visit http://www.tik.ee.ethz.ch/~topsy This software is provided under the terms of the GNU General Public Licence. A full copy of the GNU GPL is provided in the file COPYING found in the development root of Topsy. */ /* File: $Source: /usr/drwho/vault/cvs/topsy/Topsy/IO/IOMain.c,v $ Author(s): George Fankhauser Affiliation: ETH Zuerich, TIK Version: $Revision: 1.40 $ Creation Date: Last Date of Change: $Date: 2000/06/05 14:06:26 $ by: $Author: gfa $ $Log: IOMain.c,v $ Revision 1.40 2000/06/05 14:06:26 gfa *** empty log message *** Revision 1.39 2000/04/05 12:04:57 gfa *** empty log message *** Revision 1.38 1999/12/13 21:48:25 ruf GNU General Public Licence Update Revision 1.37 1999/10/31 14:42:44 jeker first fixes for SimOS Revision 1.36 1999/10/23 21:31:03 gfa *** empty log message *** Revision 1.35 1999/10/21 20:22:22 jeker first commit for the R4k support Revision 1.34 1999/09/13 07:56:47 gfa added thread id field to device struct Revision 1.33 1999/06/06 20:54:46 jeker putting everything together for Topsy 2.0 Revision 1.32 1999/04/08 11:40:08 jeker added some new files, modified some others for unix port Revision 1.31 1998/04/14 12:20:13 gfa grrr, SCN makes trouble for kernel output (SCN init? wait after?) Revision 1.30 1998/04/08 15:10:08 gfa reformatted output for driver load/init Revision 1.29 1998/03/31 18:53:05 gries comment added Revision 1.28 1998/03/31 17:48:50 gries no more PutStrings while initializing interrupt handlers Revision 1.27 1998/03/31 16:13:47 gries DeviceDesc added for timer1 as comment Revision 1.26 1997/06/01 17:10:45 gfa removed an unnecessary wait... * Revision 1.25 1997/05/30 18:02:53 gfa * added loopback device * * Revision 1.24 1997/05/16 14:38:40 stauffer * display information added * * Revision 1.23 1997/05/07 16:57:05 stauffer * errors corrected * * Revision 1.21 1997/04/21 07:24:10 conrad * cleanup * * Revision 1.20 1997/04/18 16:27:58 conrad * *** empty log message *** * * Revision 1.19 1997/04/17 11:03:06 conrad * fixed sequence between ttya and ttyb * * Revision 1.18 1997/04/14 21:06:08 conrad * UART Problem * * Revision 1.17 1997/04/13 15:31:24 gfa * added handling of excess unknown syscall answers * * Revision 1.16 1997/04/12 13:02:43 gfa * added NIL test for interrupt handlers * * Revision 1.15 1997/04/08 13:05:24 conrad * change of tmStart() syscall * * Revision 1.14 1997/04/07 13:26:45 gfa * adapted calls for framework * * Revision 1.13 97/04/06 18:58:20 gfa * source cleanup * * Revision 1.12 1997/03/28 12:09:22 gfa * changed name of tmStart (was tmThreadStart) * * Revision 1.11 1997/03/19 22:38:25 gfa * *** empty log message *** * * Revision 1.10 1997/03/19 07:25:15 gfa * *** empty log message *** * * Revision 1.9 1997/03/17 08:34:29 gfa * *** empty log message *** * * Revision 1.8 1997/03/16 22:15:30 gfa * *** empty log message *** * * Revision 1.7 1997/03/14 14:14:29 gfa * fixed expectedFrom (int/int*) type conflict in tmMsgRecv * * Revision 1.6 1997/02/24 07:39:20 gfa * *** empty log message *** * * Revision 1.5 1997/02/21 08:58:15 conrad * Adding of ANYMSGTYPE parameter to tmMsgRecv() * * Revision 1.4 1997/02/17 16:51:34 gfa * first implementation * * Revision 1.3 1997/02/13 15:46:18 conrad * First compilation/linking of complete environment (all modules) * * Revision 1.2 1997/02/12 15:30:58 gfa * full interface defined, msg handler first version * * Revision 1.1 1997/02/11 17:13:29 gfa * Initial revision * * Revision 1.1 1997/02/04 11:20:51 topsy * Initial revision * */ #include "IO.h" #include "IOMain.h" #include "IODevice.h" #include "Syscall.h" #include "Threads.h" #include "Exception.h" #include "IODevTable.h" static void ioLoadDriver(int number, IODevice dev); /* The table has been moved to the architecture depending files */ static HashList ioDevices; /* IO thread main procedure */ void ioMain(ThreadArg arg) { int i; Error error; ThreadId t; ThreadId expectedFrom; Message msg, reply; DriverMessage driverMsg; ioDevices = hashListNew(); ioConsolePutString("ioThread: loading "); ioConsolePutInt(IO_DEVCOUNT); ioConsolePutString(" drivers...\n"); /* due to the centralized interrupt handling in certain UARTs we * need to know each other */ #ifdef IO_SERIAL_B /* a hack for Architectures where no IO_SERIAL_A and IO_SERIAL_B is defined */ ioDeviceTable[IO_SERIAL_A].extension = &(ioDeviceTable[IO_SERIAL_B]); #endif for (i = 0; i < IO_DEVCOUNT; i++) { if (ioDeviceTable[i].init != NULL) { ioDeviceTable[i].init( &(ioDeviceTable[i]) ); } } for (i = 0; i < IO_DEVCOUNT; i++) { ioLoadDriver(i, &(ioDeviceTable[i])); } while (TRUE) { expectedFrom = ANY; tmMsgRecv(&expectedFrom, ANYMSGTYPE, &msg, INFINITY); switch (msg.id) { case IO_OPEN: error = hashListGet(ioDevices, (void**)(&t), msg.msg.ioOpen.deviceNumber); reply.id = IO_OPENREPLY; if (error == HASHNOTFOUND) { reply.msg.ioOpenReply.errorCode = IO_OPENFAILED; } else { reply.msg.ioOpenReply.errorCode = IO_OPENOK; } reply.msg.ioOpenReply.deviceThreadId = t; tmMsgSend(msg.from, &reply); break; case IO_CLOSE: /* msg is forwarded to driver thread or fails if id is wrong */ driverMsg.id = IO_DRIVERCLOSE; driverMsg.clientThreadId = msg.from; error = tmMsgSend(msg.msg.ioClose.deviceThreadId, (Message*)&driverMsg); if (error != TM_MSGSENDOK) { reply.id = IO_CLOSEREPLY; reply.msg.ioCloseReply.errorCode = IO_CLOSEFAILED; tmMsgSend(msg.from, &reply); } /* drivers actions: send reply to syscaller, clean up */ break; case UNKNOWN_SYSCALL: /* possible reply on garbage IO_CLOSE forward */ break; default: /* return error */ reply.id = UNKNOWN_SYSCALL; tmMsgSend(msg.from, &reply); } } } static void ioLoadDriver(int number, IODevice dev) { ThreadId t; if (dev->interruptHandler != NULL && (dev->interrupt > 0) ) { (void)tmSetInterruptHandler(dev->interrupt, dev->interruptHandler,dev); } /* main function is for all devices the same */ if (tmStart( &t, (ThreadMainFunction)ioDeviceMain, dev, dev->name) != TM_STARTOK) { ERROR("Driver could not be started\n"); } /* save thread id for handy access to kSend from interrupt */ dev->threadId = t; /* track the numbers to be able to open drivers later */ hashListAdd(ioDevices, (void*)t, number); }