Subversion Repositories HelenOS

Rev

Rev 3150 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3150 Rev 3403
Line 79... Line 79...
79
{
79
{
80
    ipc_callid_t callid;
80
    ipc_callid_t callid;
81
    ipc_call_t call;
81
    ipc_call_t call;
82
    int retval;
82
    int retval;
83
    void *fs_va = NULL;
83
    void *fs_va = NULL;
84
    ipcarg_t offset;
84
    off_t offset;
-
 
85
    size_t block_size;
-
 
86
    size_t maxblock_size;
85
 
87
 
86
    /*
88
    /*
87
     * We allocate VA for communication per connection.
89
     * Answer the first IPC_M_CONNECT_ME_TO call.
88
     * This allows us to potentionally have more clients and work
-
 
89
     * concurrently.
-
 
90
     */
90
     */
91
    fs_va = as_get_mappable_page(ALIGN_UP(BLOCK_SIZE, PAGE_SIZE));
-
 
92
    if (!fs_va) {
-
 
93
        /*
-
 
94
         * Hang up the phone if we cannot proceed any further.
-
 
95
         * This is the answer to the call that opened the connection.
-
 
96
         */
-
 
97
        ipc_answer_0(iid, EHANGUP);
91
    ipc_answer_0(iid, EOK);
98
        return;
-
 
99
    } else {
-
 
100
        /*
-
 
101
         * Answer the first IPC_M_CONNECT_ME_TO call.
-
 
102
         * Return supported block size as ARG1.
-
 
103
         */
-
 
104
        ipc_answer_1(iid, EOK, BLOCK_SIZE);
-
 
105
    }
-
 
106
 
92
 
107
    /*
93
    /*
108
     * Now we wait for the client to send us its communication as_area.
94
     * Now we wait for the client to send us its communication as_area.
109
     */
95
     */
110
    size_t size;
-
 
111
    int flags;
96
    int flags;
112
    if (ipc_share_out_receive(&callid, &size, &flags)) {
97
    if (ipc_share_out_receive(&callid, &maxblock_size, &flags)) {
113
        if (size >= BLOCK_SIZE) {
-
 
114
            /*
-
 
115
             * The client sends an as_area that can absorb the whole
98
        fs_va = as_get_mappable_page(maxblock_size);
116
             * block.
99
        if (fs_va) {
117
             */
-
 
118
            (void) ipc_share_out_finalize(callid, fs_va);
100
            (void) ipc_share_out_finalize(callid, fs_va);
119
        } else {
101
        } else {
120
            /*
-
 
121
             * The client offered as_area too small.
-
 
122
             * Close the connection.
-
 
123
             */
-
 
124
            ipc_answer_0(callid, EHANGUP);
102
            ipc_answer_0(callid, EHANGUP);
125
            return;    
103
            return;    
126
        }
104
        }
127
    } else {
105
    } else {
128
        /*
106
        /*
Line 144... Line 122...
144
             */
122
             */
145
            ipc_answer_0(callid, EOK);
123
            ipc_answer_0(callid, EOK);
146
            return;
124
            return;
147
        case RD_READ_BLOCK:
125
        case RD_READ_BLOCK:
148
            offset = IPC_GET_ARG1(call);
126
            offset = IPC_GET_ARG1(call);
-
 
127
            block_size = IPC_GET_ARG2(call);
-
 
128
            if (block_size > maxblock_size) {
-
 
129
                /*
-
 
130
                 * Maximum block size exceeded.
-
 
131
                 */
-
 
132
                retval = ELIMIT;
-
 
133
                break;
-
 
134
            }
149
            if (offset * BLOCK_SIZE > rd_size - BLOCK_SIZE) {
135
            if (offset * block_size > rd_size - block_size) {
150
                /*
136
                /*
151
                 * Reading past the end of the device.
137
                 * Reading past the end of the device.
152
                 */
138
                 */
153
                retval = ELIMIT;
139
                retval = ELIMIT;
154
                break;
140
                break;
155
            }
141
            }
156
            futex_down(&rd_futex);
142
            futex_down(&rd_futex);
157
            memcpy(fs_va, rd_addr + offset * BLOCK_SIZE, BLOCK_SIZE);
143
            memcpy(fs_va, rd_addr + offset * block_size, block_size);
158
            futex_up(&rd_futex);
144
            futex_up(&rd_futex);
159
            retval = EOK;
145
            retval = EOK;
160
            break;
146
            break;
161
        case RD_WRITE_BLOCK:
147
        case RD_WRITE_BLOCK:
162
            offset = IPC_GET_ARG1(call);
148
            offset = IPC_GET_ARG1(call);
-
 
149
            block_size = IPC_GET_ARG2(call);
-
 
150
            if (block_size > maxblock_size) {
-
 
151
                /*
-
 
152
                 * Maximum block size exceeded.
-
 
153
                 */
-
 
154
                retval = ELIMIT;
-
 
155
                break;
-
 
156
            }
163
            if (offset * BLOCK_SIZE > rd_size - BLOCK_SIZE) {
157
            if (offset * block_size > rd_size - block_size) {
164
                /*
158
                /*
165
                 * Writing past the end of the device.
159
                 * Writing past the end of the device.
166
                 */
160
                 */
167
                retval = ELIMIT;
161
                retval = ELIMIT;
168
                break;
162
                break;
169
            }
163
            }
170
            futex_up(&rd_futex);
164
            futex_up(&rd_futex);
171
            memcpy(rd_addr + offset * BLOCK_SIZE, fs_va, BLOCK_SIZE);
165
            memcpy(rd_addr + offset * block_size, fs_va, block_size);
172
            futex_down(&rd_futex);
166
            futex_down(&rd_futex);
173
            retval = EOK;
167
            retval = EOK;
174
            break;
168
            break;
175
        default:
169
        default:
176
            /*
170
            /*