source: trunk/kernel/kern/chdev.c @ 16

Last change on this file since 16 was 16, checked in by alain, 5 years ago

mprove the HAL for interrupt, exception, syscall handling.

File size: 6.2 KB
Line 
1/*
2 * chdev.c - channel device descriptor operations implementation.
3 *
4 * Authors  Alain Greiner   (2016)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH.is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH.is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH.; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <kernel_config.h>
25#include <hal_types.h>
26#include <hal_special.h>
27#include <printk.h>
28#include <boot_info.h>
29#include <xlist.h>
30#include <kmem.h>
31#include <thread.h>
32#include <rpc.h>
33#include <chdev.h>
34
35////////////////////////////////////////////
36char * chdev_func_str( uint32_t func_type ) 
37{
38        if     ( func_type == DEV_FUNC_RAM ) return "RAM";
39        else if( func_type == DEV_FUNC_ROM ) return "ROM";
40        else if( func_type == DEV_FUNC_FBF ) return "FBF";
41        else if( func_type == DEV_FUNC_IOB ) return "IOB";
42        else if( func_type == DEV_FUNC_IOC ) return "IOC";
43        else if( func_type == DEV_FUNC_MMC ) return "MMC";
44        else if( func_type == DEV_FUNC_DMA ) return "DMA";
45        else if( func_type == DEV_FUNC_NIC ) return "NIC";
46        else if( func_type == DEV_FUNC_TIM ) return "TIM";
47        else if( func_type == DEV_FUNC_TXT ) return "TXT";
48        else if( func_type == DEV_FUNC_ICU ) return "ICU";
49        else if( func_type == DEV_FUNC_PIC ) return "PIC";
50    else                                 return "undefined";
51}
52
53/////////////////////////////////////////
54chdev_t * chdev_create( uint32_t    func,
55                        uint32_t    impl,
56                        uint32_t    channel,
57                        uint32_t    is_rx,
58                        xptr_t      base )
59{
60    chdev_t    * chdev;
61    kmem_req_t   req;
62
63    // allocate memory for chdev
64    req.type   = KMEM_DEVICE;
65    req.flags  = AF_ZERO;
66    chdev      = (chdev_t *)kmem_alloc( &req );
67
68    if( chdev == NULL ) return NULL;
69
70    // initialize waiting threads queue and associated lock
71    remote_spinlock_init( XPTR( local_cxy , &chdev->wait_lock ) );
72    xlist_root_init( XPTR( local_cxy , &chdev->wait_root ) );
73
74    // initialize attributes
75    chdev->func    =  func;
76    chdev->impl    =  impl;
77    chdev->channel =  channel;
78    chdev->is_rx   =  is_rx;
79    chdev->base    =  base; 
80
81    return chdev;
82
83}  // end chdev_create()
84
85///////////////////////////////////
86void chdev_print( chdev_t * chdev )
87{
88    printk("\n - func      = %s"
89           "\n - channel   = %d"
90           "\n - base      = %l"
91           "\n - cmd       = %x"
92           "\n - isr       = %x"
93           "\n - chdev     = %x\n",
94           chdev_func_str(chdev->func),
95           chdev->channel,
96           chdev->base,
97           chdev->cmd,
98           chdev->isr,
99           chdev );
100}
101
102////////////////////////////////////////////////
103void chdev_register_command( xptr_t     chdev_xp,
104                             thread_t * thread )
105{
106    thread_t * thread_ptr = CURRENT_THREAD;
107
108    // get device descriptor cluster and local pointer
109    cxy_t     chdev_cxy = GET_CXY( chdev_xp );
110    chdev_t * chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
111
112    // build extended pointers on client thread xlist and device root
113    xptr_t  xp_list = XPTR( local_cxy , &thread_ptr->wait_list );
114    xptr_t  xp_root = XPTR( chdev_cxy , &chdev_ptr->wait_root );
115
116    // get lock protecting queue
117    remote_spinlock_lock( XPTR( chdev_cxy , &chdev_ptr->wait_lock ) );
118
119    // register client thread in waiting queue
120    xlist_add_last( xp_root , xp_list );
121
122    // unblock server thread
123    thread_unblock( XPTR( chdev_cxy , &chdev_ptr->server ) , THREAD_BLOCKED_DEV_QUEUE );
124
125    // release lock
126    remote_spinlock_unlock( XPTR( chdev_cxy , &chdev_ptr->wait_lock ) );
127
128    // client thread goes to blocked state and deschedule
129    thread_block( thread_ptr , THREAD_BLOCKED_IO );
130    sched_yield();
131
132}  // end chdev_register_command()
133
134///////////////////////////////////////////////
135void chdev_sequencial_server( chdev_t * chdev )
136{
137    xptr_t          client_xp;    // extended pointer on waiting thread
138    cxy_t           client_cxy;   // cluster of client thread
139    thread_t      * client_ptr;   // local pointer on client thread
140    thread_t      * server;       // local pointer on this thread
141    xptr_t          root_xp;      // extended pointer on device waiting queue root
142
143    server = CURRENT_THREAD;
144
145    root_xp = XPTR( local_cxy , &chdev->wait_root );
146
147    // take the lock protecting the chdev waiting queue, before entering the
148        // infinite loop handling commands registered in this queue.
149    // In the loop, the lock is released during the handling of one command.
150
151    remote_spinlock_lock( XPTR( local_cxy , &chdev->wait_lock ) );
152
153    while( 1 )
154    {
155        // check waiting queue state
156        if( xlist_is_empty( root_xp ) ) // block and deschedule if waiting queue empty
157        {
158            // release lock
159            remote_spinlock_unlock( XPTR( local_cxy , &chdev->wait_lock ) );
160
161            // block and deschedule
162            thread_block( server , THREAD_BLOCKED_DEV_QUEUE );
163            sched_yield();
164        } 
165        else
166        {
167            // release lock
168            remote_spinlock_unlock( XPTR( local_cxy , &chdev->wait_lock ) );
169        }
170
171        // get extended pointer on first client thread
172        client_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list );
173
174        // call driver command function to execute I/O operation
175        chdev->cmd( client_xp );
176       
177        // get client thread cluster and local pointer
178        client_cxy = GET_CXY( client_xp );
179        client_ptr = (thread_t *)GET_PTR( client_xp );
180
181        // take the lock, and remove the client thread from waiting queue
182        remote_spinlock_lock( XPTR( local_cxy , &chdev->wait_lock ) );
183        xlist_unlink( XPTR( client_cxy , &client_ptr->wait_list ) );
184
185    }  // end while
186
187}  // end chdev_sequencial_server()
188
Note: See TracBrowser for help on using the repository browser.