Bug Summary

File:obj-scan-build/../linux/pcmcia-cs/modules/bulkmem.c
Location:line 72, column 5
Description:Value stored to 's' is never read

Annotated Source Code

1/*======================================================================
2
3 PCMCIA Bulk Memory Services
4
5 bulkmem.c 1.44 2002/06/29 06:23:09
6
7 The contents of this file are subject to the Mozilla Public
8 License Version 1.1 (the "License"); you may not use this file
9 except in compliance with the License. You may obtain a copy of
10 the License at http://www.mozilla.org/MPL/
11
12 Software distributed under the License is distributed on an "AS
13 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 implied. See the License for the specific language governing
15 rights and limitations under the License.
16
17 The initial developer of the original code is David A. Hinds
18 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
20
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU General Public License version 2 (the "GPL"), in
23 which case the provisions of the GPL are applicable instead of the
24 above. If you wish to allow the use of your version of this file
25 only under the terms of the GPL and not to allow others to use
26 your version of this file under the MPL, indicate your decision
27 by deleting the provisions above and replace them with the notice
28 and other provisions required by the GPL. If you do not delete
29 the provisions above, a recipient may use your version of this
30 file under either the MPL or the GPL.
31
32======================================================================*/
33
34#define __NO_VERSION__
35
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/string.h>
39#include <linux/errno.h>
40#include <linux/slab.h>
41#include <linux/mm.h>
42#include <linux/sched.h>
43#include <linux/timer.h>
44
45#define IN_CARD_SERVICES
46#include <pcmcia/cs_types.h>
47#include <pcmcia/ss.h>
48#include <pcmcia/cs.h>
49#include <pcmcia/bulkmem.h>
50#include <pcmcia/cistpl.h>
51#include "cs_internal.h"
52
53/*======================================================================
54
55 This function handles submitting an MTD request, and retrying
56 requests when an MTD is busy.
57
58 An MTD request should never block.
59
60======================================================================*/
61
62static int do_mtd_request(memory_handle_t handle, mtd_request_t *req,
63 caddr_t buf)
64{
65 int ret, tries;
66 client_t *mtd;
67 socket_info_t *s;
68
69 mtd = handle->mtd;
70 if (mtd == NULL((void *) 0))
71 return CS_GENERAL_FAILURE0x19;
72 s = SOCKET(mtd)(socket_table[(mtd)->Socket]);
Value stored to 's' is never read
73 for (ret = tries = 0; tries < 100; tries++) {
74 mtd->event_callback_args.mtdrequest = req;
75 mtd->event_callback_args.buffer = buf;
76 ret = EVENT(mtd, CS_EVENT_MTD_REQUEST, CS_EVENT_PRI_LOW)((mtd)->event_handler((0x020000), (0), &(mtd)->event_callback_args
))
;
77 if (ret != CS_BUSY0x18)
78 break;
79 switch (req->Status) {
80 case MTD_WAITREQ0x00:
81 /* Not that we should ever need this... */
82 interruptible_sleep_on_timeout(&mtd->mtd_req, HZ)interruptible_sleep_on(&mtd->mtd_req);
83 break;
84 case MTD_WAITTIMER0x01:
85 case MTD_WAITRDY0x02:
86 interruptible_sleep_on_timeout(&mtd->mtd_req,interruptible_sleep_on(&mtd->mtd_req)
87 req->Timeout*HZ/1000)interruptible_sleep_on(&mtd->mtd_req);
88 req->Function |= MTD_REQ_TIMEOUT0x020;
89 break;
90 case MTD_WAITPOWER0x03:
91 interruptible_sleep_on(&mtd->mtd_req);
92 break;
93 }
94 if (signal_pending(current)0)
95 printk(KERN_NOTICE"<5>" "cs: do_mtd_request interrupted!\n");
96 }
97 if (tries == 20) {
98 printk(KERN_NOTICE"<5>" "cs: MTD request timed out!\n");
99 ret = CS_GENERAL_FAILURE0x19;
100 }
101 wake_up_interruptiblewake_up(&mtd->mtd_req);
102 retry_erase_list(&mtd->erase_busy, 0);
103 return ret;
104} /* do_mtd_request */
105
106/*======================================================================
107
108 This stuff is all for handling asynchronous erase requests. It
109 is complicated because all the retry stuff has to be dealt with
110 in timer interrupts or in the card status event handler.
111
112======================================================================*/
113
114static void insert_queue(erase_busy_t *head, erase_busy_t *entry)
115{
116 DEBUG(2, "cs: adding 0x%p to queue 0x%p\n", entry, head)do { if (pc_debug>(2)) printk("<7>" "cs: adding 0x%p to queue 0x%p\n"
, entry, head); } while (0)
;
117 entry->next = head;
118 entry->prev = head->prev;
119 head->prev->next = entry;
120 head->prev = entry;
121}
122
123static void remove_queue(erase_busy_t *entry)
124{
125 DEBUG(2, "cs: unqueueing 0x%p\n", entry)do { if (pc_debug>(2)) printk("<7>" "cs: unqueueing 0x%p\n"
, entry); } while (0)
;
126 entry->next->prev = entry->prev;
127 entry->prev->next = entry->next;
128}
129
130static void retry_erase(erase_busy_t *busy, u_int cause)
131{
132 eraseq_entry_t *erase = busy->erase;
133 mtd_request_t req;
134 client_t *mtd;
135 socket_info_t *s;
136 int ret;
137
138 DEBUG(2, "cs: trying erase request 0x%p...\n", busy)do { if (pc_debug>(2)) printk("<7>" "cs: trying erase request 0x%p...\n"
, busy); } while (0)
;
139 if (busy->next)
140 remove_queue(busy);
141 req.Function = MTD_REQ_ERASE0x000 | cause;
142 req.TransferLength = erase->Size;
143 req.DestCardOffset = erase->Offset + erase->Handle->info.CardOffset;
144 req.MediaID = erase->Handle->MediaID;
145 mtd = erase->Handle->mtd;
146 s = SOCKET(mtd)(socket_table[(mtd)->Socket]);
147 mtd->event_callback_args.mtdrequest = &req;
148 ret = EVENT(mtd, CS_EVENT_MTD_REQUEST, CS_EVENT_PRI_LOW)((mtd)->event_handler((0x020000), (0), &(mtd)->event_callback_args
))
;
149 if (ret == CS_BUSY0x18) {
150 DEBUG(2, " Status = %d, requeueing.\n", req.Status)do { if (pc_debug>(2)) printk("<7>" " Status = %d, requeueing.\n"
, req.Status); } while (0)
;
151 switch (req.Status) {
152 case MTD_WAITREQ0x00:
153 case MTD_WAITPOWER0x03:
154 insert_queue(&mtd->erase_busy, busy);
155 break;
156 case MTD_WAITTIMER0x01:
157 case MTD_WAITRDY0x02:
158 if (req.Status == MTD_WAITRDY0x02)
159 insert_queue(&s->erase_busy, busy);
160 mod_timer(&busy->timeout, jiffies + req.Timeout*HZ/1000)do { del_timer(&busy->timeout); (&busy->timeout
)->expires = (jiffies + req.Timeout*100/1000); add_timer(&
busy->timeout); } while (0)
;
161 break;
162 }
163 } else {
164 /* update erase queue status */
165 DEBUG(2, " Ret = %d\n", ret)do { if (pc_debug>(2)) printk("<7>" " Ret = %d\n", ret
); } while (0)
;
166 switch (ret) {
167 case CS_SUCCESS0x00:
168 erase->State = ERASE_PASSED0xe0; break;
169 case CS_WRITE_PROTECTED0x1a:
170 erase->State = ERASE_MEDIA_WRPROT0x84; break;
171 case CS_BAD_OFFSET0x07:
172 erase->State = ERASE_BAD_OFFSET0xc1; break;
173 case CS_BAD_SIZE0x0a:
174 erase->State = ERASE_BAD_SIZE0xc6; break;
175 case CS_NO_CARD0x14:
176 erase->State = ERASE_BAD_SOCKET0xc3; break;
177 default:
178 erase->State = ERASE_FAILED0xe1; break;
179 }
180 busy->client->event_callback_args.info = erase;
181 EVENT(busy->client, CS_EVENT_ERASE_COMPLETE, CS_EVENT_PRI_LOW)((busy->client)->event_handler((0x040000), (0), &(busy
->client)->event_callback_args))
;
182 kfreelinux_kfree(busy);
183 /* Resubmit anything waiting for a request to finish */
184 wake_up_interruptiblewake_up(&mtd->mtd_req);
185 retry_erase_list(&mtd->erase_busy, 0);
186 }
187} /* retry_erase */
188
189void retry_erase_list(erase_busy_t *list, u_int cause)
190{
191 erase_busy_t tmp = *list;
192
193 DEBUG(2, "cs: rescanning erase queue list 0x%p\n", list)do { if (pc_debug>(2)) printk("<7>" "cs: rescanning erase queue list 0x%p\n"
, list); } while (0)
;
194 if (list->next == list)
195 return;
196 /* First, truncate the original list */
197 list->prev->next = &tmp;
198 list->next->prev = &tmp;
199 list->prev = list->next = list;
200 tmp.prev->next = &tmp;
201 tmp.next->prev = &tmp;
202
203 /* Now, retry each request, in order. */
204 while (tmp.next != &tmp)
205 retry_erase(tmp.next, cause);
206} /* retry_erase_list */
207
208static void handle_erase_timeout(u_long arg)
209{
210 DEBUG(0, "cs: erase timeout for entry 0x%lx\n", arg)do { if (pc_debug>(0)) printk("<7>" "cs: erase timeout for entry 0x%lx\n"
, arg); } while (0)
;
211 retry_erase((erase_busy_t *)arg, MTD_REQ_TIMEOUT0x020);
212}
213
214static void setup_erase_request(client_handle_t handle, eraseq_entry_t *erase)
215{
216 erase_busy_t *busy;
217 region_info_t *info;
218
219 if (CHECK_REGION(erase->Handle)(((erase->Handle) == ((void *) 0)) || ((erase->Handle)->
region_magic != 0xE3C9))
)
220 erase->State = ERASE_BAD_SOCKET0xc3;
221 else {
222 info = &erase->Handle->info;
223 if ((erase->Offset >= info->RegionSize) ||
224 (erase->Offset & (info->BlockSize-1)))
225 erase->State = ERASE_BAD_OFFSET0xc1;
226 else if ((erase->Offset+erase->Size > info->RegionSize) ||
227 (erase->Size & (info->BlockSize-1)))
228 erase->State = ERASE_BAD_SIZE0xc6;
229 else {
230 erase->State = 1;
231 busy = kmalloclinux_kmalloc(sizeof(erase_busy_t), GFP_KERNEL0x03);
232 busy->erase = erase;
233 busy->client = handle;
234 init_timer(&busy->timeout);
235 busy->timeout.data = (u_long)busy;
236 busy->timeout.function = &handle_erase_timeout;
237 busy->prev = busy->next = NULL((void *) 0);
238 retry_erase(busy, 0);
239 }
240 }
241} /* setup_erase_request */
242
243/*======================================================================
244
245 MTD helper functions
246
247======================================================================*/
248
249static int mtd_modify_window(window_handle_t win, mtd_mod_win_t *req)
250{
251 if ((win == NULL((void *) 0)) || (win->magic != WINDOW_MAGIC0xB35C))
252 return CS_BAD_HANDLE0x21;
253 win->ctl.flags = MAP_16BIT0x02 | MAP_ACTIVE0x01;
254 if (req->Attributes & WIN_USE_WAIT0x0100)
255 win->ctl.flags |= MAP_USE_WAIT0x40;
256 if (req->Attributes & WIN_MEMORY_TYPE0x0002)
257 win->ctl.flags |= MAP_ATTRIB0x20;
258 win->ctl.speed = req->AccessSpeed;
259 win->ctl.card_start = req->CardOffset;
260 win->sock->ss_entry(win->sock->sock, SS_SetMemMap, &win->ctl);
261 return CS_SUCCESS0x00;
262}
263
264static int mtd_set_vpp(client_handle_t handle, mtd_vpp_req_t *req)
265{
266 socket_info_t *s;
267 if (CHECK_HANDLE(handle)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
268 return CS_BAD_HANDLE0x21;
269 if (req->Vpp1 != req->Vpp2)
270 return CS_BAD_VPP0x0f;
271 s = SOCKET(handle)(socket_table[(handle)->Socket]);
272 s->socket.Vpp = req->Vpp1;
273 if (s->ss_entry(s->sock, SS_SetSocket, &s->socket))
274 return CS_BAD_VPP0x0f;
275 return CS_SUCCESS0x00;
276}
277
278static int mtd_rdy_mask(client_handle_t handle, mtd_rdy_req_t *req)
279{
280 socket_info_t *s;
281 if (CHECK_HANDLE(handle)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
282 return CS_BAD_HANDLE0x21;
283 s = SOCKET(handle)(socket_table[(handle)->Socket]);
284 if (req->Mask & CS_EVENT_READY_CHANGE0x000040)
285 s->socket.csc_mask |= SS_READY0x0040;
286 else
287 s->socket.csc_mask &= ~SS_READY0x0040;
288 if (s->ss_entry(s->sock, SS_SetSocket, &s->socket))
289 return CS_GENERAL_FAILURE0x19;
290 return CS_SUCCESS0x00;
291}
292
293int MTDHelperEntry(int func, void *a1, void *a2)
294{
295 switch (func) {
296 case MTDRequestWindow:
297 return CardServices(RequestWindow, a1, a2, NULL((void *) 0));
298 case MTDReleaseWindow:
299 return CardServices(ReleaseWindow, a1, NULL((void *) 0), NULL((void *) 0));
300 case MTDModifyWindow:
301 return mtd_modify_window(a1, a2); break;
302 case MTDSetVpp:
303 return mtd_set_vpp(a1, a2); break;
304 case MTDRDYMask:
305 return mtd_rdy_mask(a1, a2); break;
306 default:
307 return CS_UNSUPPORTED_FUNCTION0x15; break;
308 }
309} /* MTDHelperEntry */
310
311/*======================================================================
312
313 This stuff is used by Card Services to initialize the table of
314 region info used for subsequent calls to GetFirstRegion and
315 GetNextRegion.
316
317======================================================================*/
318
319static void setup_regions(client_handle_t handle, int attr,
320 memory_handle_t *list)
321{
322 int i, code, has_jedec, has_geo;
323 u_int offset;
324 cistpl_device_t device;
325 cistpl_jedec_t jedec;
326 cistpl_device_geo_t geo;
327 memory_handle_t r;
328
329 DEBUG(1, "cs: setup_regions(0x%p, %d, 0x%p)\n",do { if (pc_debug>(1)) printk("<7>" "cs: setup_regions(0x%p, %d, 0x%p)\n"
, handle, attr, list); } while (0)
330 handle, attr, list)do { if (pc_debug>(1)) printk("<7>" "cs: setup_regions(0x%p, %d, 0x%p)\n"
, handle, attr, list); } while (0)
;
331
332 code = (attr) ? CISTPL_DEVICE_A0x17 : CISTPL_DEVICE0x01;
333 if (read_tuple(handle, code, &device) != CS_SUCCESS0x00)
334 return;
335 code = (attr) ? CISTPL_JEDEC_A0x19 : CISTPL_JEDEC_C0x18;
336 has_jedec = (read_tuple(handle, code, &jedec) == CS_SUCCESS0x00);
337 if (has_jedec && (device.ndev != jedec.nid)) {
338#ifdef PCMCIA_DEBUG4
339 printk(KERN_DEBUG"<7>" "cs: Device info does not match JEDEC info.\n");
340#endif
341 has_jedec = 0;
342 }
343 code = (attr) ? CISTPL_DEVICE_GEO_A0x1f : CISTPL_DEVICE_GEO0x1e;
344 has_geo = (read_tuple(handle, code, &geo) == CS_SUCCESS0x00);
345 if (has_geo && (device.ndev != geo.ngeo)) {
346#ifdef PCMCIA_DEBUG4
347 printk(KERN_DEBUG"<7>" "cs: Device info does not match geometry tuple.\n");
348#endif
349 has_geo = 0;
350 }
351
352 offset = 0;
353 for (i = 0; i < device.ndev; i++) {
354 if ((device.dev[i].type != CISTPL_DTYPE_NULL0x00) &&
355 (device.dev[i].size != 0)) {
356 r = kmalloclinux_kmalloc(sizeof(*r), GFP_KERNEL0x03);
357 r->region_magic = REGION_MAGIC0xE3C9;
358 r->state = 0;
359 r->dev_info[0] = '\0';
360 r->mtd = NULL((void *) 0);
361 r->info.Attributes = (attr) ? REGION_TYPE_AM0x0001 : 0;
362 r->info.CardOffset = offset;
363 r->info.RegionSize = device.dev[i].size;
364 r->info.AccessSpeed = device.dev[i].speed;
365 if (has_jedec) {
366 r->info.JedecMfr = jedec.id[i].mfr;
367 r->info.JedecInfo = jedec.id[i].info;
368 } else
369 r->info.JedecMfr = r->info.JedecInfo = 0;
370 if (has_geo) {
371 r->info.BlockSize = geo.geo[i].buswidth *
372 geo.geo[i].erase_block * geo.geo[i].interleave;
373 r->info.PartMultiple =
374 r->info.BlockSize * geo.geo[i].partition;
375 } else
376 r->info.BlockSize = r->info.PartMultiple = 1;
377 r->info.next = *list; *list = r;
378 }
379 offset += device.dev[i].size;
380 }
381} /* setup_regions */
382
383/*======================================================================
384
385 This is tricky. When get_first_region() is called by Driver
386 Services, we initialize the region info table in the socket
387 structure. When it is called by an MTD, we can just scan the
388 table for matching entries.
389
390======================================================================*/
391
392static int match_region(client_handle_t handle, memory_handle_t list,
393 region_info_t *match)
394{
395 while (list != NULL((void *) 0)) {
396 if (!(handle->Attributes & INFO_MTD_CLIENT0x04) ||
397 (strcmp(handle->dev_info, list->dev_info) == 0)) {
398 *match = list->info;
399 return CS_SUCCESS0x00;
400 }
401 list = list->info.next;
402 }
403 return CS_NO_MORE_ITEMS0x1f;
404} /* match_region */
405
406int get_first_region(client_handle_t handle, region_info_t *rgn)
407{
408 socket_info_t *s = SOCKET(handle)(socket_table[(handle)->Socket]);
409 if (CHECK_HANDLE(handle)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
410 return CS_BAD_HANDLE0x21;
411
412 if ((handle->Attributes & INFO_MASTER_CLIENT0x01) &&
413 (!(s->state & SOCKET_REGION_INFO0x4000))) {
414 setup_regions(handle, 0, &s->c_region);
415 setup_regions(handle, 1, &s->a_region);
416 s->state |= SOCKET_REGION_INFO0x4000;
417 }
418
419 if (rgn->Attributes & REGION_TYPE_AM0x0001)
420 return match_region(handle, s->a_region, rgn);
421 else
422 return match_region(handle, s->c_region, rgn);
423} /* get_first_region */
424
425int get_next_region(client_handle_t handle, region_info_t *rgn)
426{
427 if (CHECK_HANDLE(handle)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
428 return CS_BAD_HANDLE0x21;
429 return match_region(handle, rgn->next, rgn);
430} /* get_next_region */
431
432/*======================================================================
433
434 Connect an MTD with a memory region.
435
436======================================================================*/
437
438int register_mtd(client_handle_t handle, mtd_reg_t *reg)
439{
440 memory_handle_t list;
441 socket_info_t *s;
442
443 if (CHECK_HANDLE(handle)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
444 return CS_BAD_HANDLE0x21;
445 s = SOCKET(handle)(socket_table[(handle)->Socket]);
446 if (reg->Attributes & REGION_TYPE_AM0x0001)
447 list = s->a_region;
448 else
449 list = s->c_region;
450 DEBUG(1, "cs: register_mtd(0x%p, '%s', 0x%x)\n",do { if (pc_debug>(1)) printk("<7>" "cs: register_mtd(0x%p, '%s', 0x%x)\n"
, handle, handle->dev_info, reg->Offset); } while (0)
451 handle, handle->dev_info, reg->Offset)do { if (pc_debug>(1)) printk("<7>" "cs: register_mtd(0x%p, '%s', 0x%x)\n"
, handle, handle->dev_info, reg->Offset); } while (0)
;
452 while (list) {
453 if (list->info.CardOffset == reg->Offset) break;
454 list = list->info.next;
455 }
456 if (list && (list->mtd == NULL((void *) 0)) &&
457 (strcmp(handle->dev_info, list->dev_info) == 0)) {
458 list->info.Attributes = reg->Attributes;
459 list->MediaID = reg->MediaID;
460 list->mtd = handle;
461 handle->mtd_count++;
462 return CS_SUCCESS0x00;
463 } else
464 return CS_BAD_OFFSET0x07;
465} /* register_mtd */
466
467/*======================================================================
468
469 Erase queue management functions
470
471======================================================================*/
472
473int register_erase_queue(client_handle_t *handle, eraseq_hdr_t *header)
474{
475 eraseq_t *queue;
476
477 if ((handle == NULL((void *) 0)) || CHECK_HANDLE(*handle)(((*handle) == ((void *) 0)) || ((*handle)->client_magic !=
0x51E6))
)
478 return CS_BAD_HANDLE0x21;
479 queue = kmalloclinux_kmalloc(sizeof(*queue), GFP_KERNEL0x03);
480 if (!queue) return CS_OUT_OF_RESOURCE0x20;
481 queue->eraseq_magic = ERASEQ_MAGIC0xFA67;
482 queue->handle = *handle;
483 queue->count = header->QueueEntryCnt;
484 queue->entry = header->QueueEntryArray;
485 *handle = (client_handle_t)queue;
486 return CS_SUCCESS0x00;
487} /* register_erase_queue */
488
489int deregister_erase_queue(eraseq_handle_t eraseq)
490{
491 int i;
492 if (CHECK_ERASEQ(eraseq)(((eraseq) == ((void *) 0)) || ((eraseq)->eraseq_magic != 0xFA67
))
)
493 return CS_BAD_HANDLE0x21;
494 for (i = 0; i < eraseq->count; i++)
495 if (ERASE_IN_PROGRESS(eraseq->entry[i].State)(((eraseq->entry[i].State) > 0) && ((eraseq->
entry[i].State) < 0x80))
) break;
496 if (i < eraseq->count)
497 return CS_BUSY0x18;
498 eraseq->eraseq_magic = 0;
499 kfreelinux_kfree(eraseq);
500 return CS_SUCCESS0x00;
501} /* deregister_erase_queue */
502
503int check_erase_queue(eraseq_handle_t eraseq)
504{
505 int i;
506 if (CHECK_ERASEQ(eraseq)(((eraseq) == ((void *) 0)) || ((eraseq)->eraseq_magic != 0xFA67
))
)
507 return CS_BAD_HANDLE0x21;
508 for (i = 0; i < eraseq->count; i++)
509 if (eraseq->entry[i].State == ERASE_QUEUED0x00)
510 setup_erase_request(eraseq->handle, &eraseq->entry[i]);
511 return CS_SUCCESS0x00;
512} /* check_erase_queue */
513
514/*======================================================================
515
516 Look up the memory region matching the request, and return a
517 memory handle.
518
519======================================================================*/
520
521int open_memory(client_handle_t *handle, open_mem_t *open)
522{
523 socket_info_t *s;
524 memory_handle_t region;
525
526 if ((handle == NULL((void *) 0)) || CHECK_HANDLE(*handle)(((*handle) == ((void *) 0)) || ((*handle)->client_magic !=
0x51E6))
)
527 return CS_BAD_HANDLE0x21;
528 s = SOCKET(*handle)(socket_table[(*handle)->Socket]);
529 if (open->Attributes & MEMORY_TYPE_AM0x0001)
530 region = s->a_region;
531 else
532 region = s->c_region;
533 while (region) {
534 if (region->info.CardOffset == open->Offset) break;
535 region = region->info.next;
536 }
537 if (region && region->mtd) {
538 *handle = (client_handle_t)region;
539 DEBUG(1, "cs: open_memory(0x%p, 0x%x) = 0x%p\n",do { if (pc_debug>(1)) printk("<7>" "cs: open_memory(0x%p, 0x%x) = 0x%p\n"
, handle, open->Offset, region); } while (0)
540 handle, open->Offset, region)do { if (pc_debug>(1)) printk("<7>" "cs: open_memory(0x%p, 0x%x) = 0x%p\n"
, handle, open->Offset, region); } while (0)
;
541 return CS_SUCCESS0x00;
542 } else
543 return CS_BAD_OFFSET0x07;
544} /* open_memory */
545
546/*======================================================================
547
548 Close a memory handle from an earlier call to OpenMemory.
549
550 For the moment, I don't think this needs to do anything.
551
552======================================================================*/
553
554int close_memory(memory_handle_t handle)
555{
556 DEBUG(1, "cs: close_memory(0x%p)\n", handle)do { if (pc_debug>(1)) printk("<7>" "cs: close_memory(0x%p)\n"
, handle); } while (0)
;
557 if (CHECK_REGION(handle)(((handle) == ((void *) 0)) || ((handle)->region_magic != 0xE3C9
))
)
558 return CS_BAD_HANDLE0x21;
559 return CS_SUCCESS0x00;
560} /* close_memory */
561
562/*======================================================================
563
564 Read from a memory device, using a handle previously returned
565 by a call to OpenMemory.
566
567======================================================================*/
568
569int read_memory(memory_handle_t handle, mem_op_t *req, caddr_t buf)
570{
571 mtd_request_t mtd;
572 if (CHECK_REGION(handle)(((handle) == ((void *) 0)) || ((handle)->region_magic != 0xE3C9
))
)
573 return CS_BAD_HANDLE0x21;
574 if (req->Offset >= handle->info.RegionSize)
575 return CS_BAD_OFFSET0x07;
576 if (req->Offset+req->Count > handle->info.RegionSize)
577 return CS_BAD_SIZE0x0a;
578
579 mtd.SrcCardOffset = req->Offset + handle->info.CardOffset;
580 mtd.TransferLength = req->Count;
581 mtd.MediaID = handle->MediaID;
582 mtd.Function = MTD_REQ_READ0x001;
583 if (req->Attributes & MEM_OP_BUFFER_KERNEL0x01)
584 mtd.Function |= MTD_REQ_KERNEL0x100;
585 return do_mtd_request(handle, &mtd, buf);
586} /* read_memory */
587
588/*======================================================================
589
590 Write to a memory device, using a handle previously returned by
591 a call to OpenMemory.
592
593======================================================================*/
594
595int write_memory(memory_handle_t handle, mem_op_t *req, caddr_t buf)
596{
597 mtd_request_t mtd;
598 if (CHECK_REGION(handle)(((handle) == ((void *) 0)) || ((handle)->region_magic != 0xE3C9
))
)
599 return CS_BAD_HANDLE0x21;
600 if (req->Offset >= handle->info.RegionSize)
601 return CS_BAD_OFFSET0x07;
602 if (req->Offset+req->Count > handle->info.RegionSize)
603 return CS_BAD_SIZE0x0a;
604
605 mtd.DestCardOffset = req->Offset + handle->info.CardOffset;
606 mtd.TransferLength = req->Count;
607 mtd.MediaID = handle->MediaID;
608 mtd.Function = MTD_REQ_WRITE0x002;
609 if (req->Attributes & MEM_OP_BUFFER_KERNEL0x01)
610 mtd.Function |= MTD_REQ_KERNEL0x100;
611 return do_mtd_request(handle, &mtd, buf);
612} /* write_memory */
613
614/*======================================================================
615
616 This isn't needed for anything I could think of.
617
618======================================================================*/
619
620int copy_memory(memory_handle_t handle, copy_op_t *req)
621{
622 if (CHECK_REGION(handle)(((handle) == ((void *) 0)) || ((handle)->region_magic != 0xE3C9
))
)
623 return CS_BAD_HANDLE0x21;
624 return CS_UNSUPPORTED_FUNCTION0x15;
625}
626