Annotation of Gnu-Mach/linux/pcmcia-cs/modules/bulkmem.c, revision 1.1.1.1

1.1       root        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:     <[email protected]>.  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: 
                     62: static 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)
                     71:        return CS_GENERAL_FAILURE;
                     72:     s = SOCKET(mtd);
                     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);
                     77:        if (ret != CS_BUSY)
                     78:            break;
                     79:        switch (req->Status) {
                     80:        case MTD_WAITREQ:
                     81:            /* Not that we should ever need this... */
                     82:            interruptible_sleep_on_timeout(&mtd->mtd_req, HZ);
                     83:            break;
                     84:        case MTD_WAITTIMER:
                     85:        case MTD_WAITRDY:
                     86:            interruptible_sleep_on_timeout(&mtd->mtd_req,
                     87:                                           req->Timeout*HZ/1000);
                     88:            req->Function |= MTD_REQ_TIMEOUT;
                     89:            break;
                     90:        case MTD_WAITPOWER:
                     91:            interruptible_sleep_on(&mtd->mtd_req);
                     92:            break;
                     93:        }
                     94:        if (signal_pending(current))
                     95:            printk(KERN_NOTICE "cs: do_mtd_request interrupted!\n");
                     96:     }
                     97:     if (tries == 20) {
                     98:        printk(KERN_NOTICE "cs: MTD request timed out!\n");
                     99:        ret = CS_GENERAL_FAILURE;
                    100:     }
                    101:     wake_up_interruptible(&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: 
                    114: static 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);
                    117:     entry->next = head;
                    118:     entry->prev = head->prev;
                    119:     head->prev->next = entry;
                    120:     head->prev = entry;
                    121: }
                    122: 
                    123: static void remove_queue(erase_busy_t *entry)
                    124: {
                    125:     DEBUG(2, "cs: unqueueing 0x%p\n", entry);
                    126:     entry->next->prev = entry->prev;
                    127:     entry->prev->next = entry->next;
                    128: }
                    129: 
                    130: static 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);
                    139:     if (busy->next)
                    140:        remove_queue(busy);
                    141:     req.Function = MTD_REQ_ERASE | 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);
                    147:     mtd->event_callback_args.mtdrequest = &req;
                    148:     ret = EVENT(mtd, CS_EVENT_MTD_REQUEST, CS_EVENT_PRI_LOW);
                    149:     if (ret == CS_BUSY) {
                    150:        DEBUG(2, "  Status = %d, requeueing.\n", req.Status);
                    151:        switch (req.Status) {
                    152:        case MTD_WAITREQ:
                    153:        case MTD_WAITPOWER:
                    154:            insert_queue(&mtd->erase_busy, busy);
                    155:            break;
                    156:        case MTD_WAITTIMER:
                    157:        case MTD_WAITRDY:
                    158:            if (req.Status == MTD_WAITRDY)
                    159:                insert_queue(&s->erase_busy, busy);
                    160:            mod_timer(&busy->timeout, jiffies + req.Timeout*HZ/1000);
                    161:            break;
                    162:        }
                    163:     } else {
                    164:        /* update erase queue status */
                    165:        DEBUG(2, "  Ret = %d\n", ret);
                    166:        switch (ret) {
                    167:        case CS_SUCCESS:
                    168:            erase->State = ERASE_PASSED; break;
                    169:        case CS_WRITE_PROTECTED:
                    170:            erase->State = ERASE_MEDIA_WRPROT; break;
                    171:        case CS_BAD_OFFSET:
                    172:            erase->State = ERASE_BAD_OFFSET; break;
                    173:        case CS_BAD_SIZE:
                    174:            erase->State = ERASE_BAD_SIZE; break;
                    175:        case CS_NO_CARD:
                    176:            erase->State = ERASE_BAD_SOCKET; break;
                    177:        default:
                    178:            erase->State = ERASE_FAILED; break;
                    179:        }
                    180:        busy->client->event_callback_args.info = erase;
                    181:        EVENT(busy->client, CS_EVENT_ERASE_COMPLETE, CS_EVENT_PRI_LOW);
                    182:        kfree(busy);
                    183:        /* Resubmit anything waiting for a request to finish */
                    184:        wake_up_interruptible(&mtd->mtd_req);
                    185:        retry_erase_list(&mtd->erase_busy, 0);
                    186:     }
                    187: } /* retry_erase */
                    188: 
                    189: void 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);
                    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: 
                    208: static void handle_erase_timeout(u_long arg)
                    209: {
                    210:     DEBUG(0, "cs: erase timeout for entry 0x%lx\n", arg);
                    211:     retry_erase((erase_busy_t *)arg, MTD_REQ_TIMEOUT);
                    212: }
                    213: 
                    214: static 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))
                    220:        erase->State = ERASE_BAD_SOCKET;
                    221:     else {
                    222:        info = &erase->Handle->info;
                    223:        if ((erase->Offset >= info->RegionSize) ||
                    224:            (erase->Offset & (info->BlockSize-1)))
                    225:            erase->State = ERASE_BAD_OFFSET;
                    226:        else if ((erase->Offset+erase->Size > info->RegionSize) ||
                    227:                 (erase->Size & (info->BlockSize-1)))
                    228:            erase->State = ERASE_BAD_SIZE;
                    229:        else {
                    230:            erase->State = 1;
                    231:            busy = kmalloc(sizeof(erase_busy_t), GFP_KERNEL);
                    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;
                    238:            retry_erase(busy, 0);
                    239:        }
                    240:     }
                    241: } /* setup_erase_request */
                    242: 
                    243: /*======================================================================
                    244: 
                    245:     MTD helper functions
                    246: 
                    247: ======================================================================*/
                    248: 
                    249: static int mtd_modify_window(window_handle_t win, mtd_mod_win_t *req)
                    250: {
                    251:     if ((win == NULL) || (win->magic != WINDOW_MAGIC))
                    252:        return CS_BAD_HANDLE;
                    253:     win->ctl.flags = MAP_16BIT | MAP_ACTIVE;
                    254:     if (req->Attributes & WIN_USE_WAIT)
                    255:        win->ctl.flags |= MAP_USE_WAIT;
                    256:     if (req->Attributes & WIN_MEMORY_TYPE)
                    257:        win->ctl.flags |= MAP_ATTRIB;
                    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_SUCCESS;
                    262: }
                    263: 
                    264: static int mtd_set_vpp(client_handle_t handle, mtd_vpp_req_t *req)
                    265: {
                    266:     socket_info_t *s;
                    267:     if (CHECK_HANDLE(handle))
                    268:        return CS_BAD_HANDLE;
                    269:     if (req->Vpp1 != req->Vpp2)
                    270:        return CS_BAD_VPP;
                    271:     s = SOCKET(handle);
                    272:     s->socket.Vpp = req->Vpp1;
                    273:     if (s->ss_entry(s->sock, SS_SetSocket, &s->socket))
                    274:        return CS_BAD_VPP;
                    275:     return CS_SUCCESS;
                    276: }
                    277: 
                    278: static int mtd_rdy_mask(client_handle_t handle, mtd_rdy_req_t *req)
                    279: {
                    280:     socket_info_t *s;
                    281:     if (CHECK_HANDLE(handle))
                    282:        return CS_BAD_HANDLE;
                    283:     s = SOCKET(handle);
                    284:     if (req->Mask & CS_EVENT_READY_CHANGE)
                    285:        s->socket.csc_mask |= SS_READY;
                    286:     else
                    287:        s->socket.csc_mask &= ~SS_READY;
                    288:     if (s->ss_entry(s->sock, SS_SetSocket, &s->socket))
                    289:        return CS_GENERAL_FAILURE;
                    290:     return CS_SUCCESS;
                    291: }
                    292: 
                    293: int MTDHelperEntry(int func, void *a1, void *a2)
                    294: {
                    295:     switch (func) {
                    296:     case MTDRequestWindow:
                    297:        return CardServices(RequestWindow, a1, a2, NULL);
                    298:     case MTDReleaseWindow:
                    299:        return CardServices(ReleaseWindow, a1, NULL, NULL);
                    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_FUNCTION; 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: 
                    319: static 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",
                    330:          handle, attr, list);
                    331: 
                    332:     code = (attr) ? CISTPL_DEVICE_A : CISTPL_DEVICE;
                    333:     if (read_tuple(handle, code, &device) != CS_SUCCESS)
                    334:        return;
                    335:     code = (attr) ? CISTPL_JEDEC_A : CISTPL_JEDEC_C;
                    336:     has_jedec = (read_tuple(handle, code, &jedec) == CS_SUCCESS);
                    337:     if (has_jedec && (device.ndev != jedec.nid)) {
                    338: #ifdef PCMCIA_DEBUG
                    339:        printk(KERN_DEBUG "cs: Device info does not match JEDEC info.\n");
                    340: #endif
                    341:        has_jedec = 0;
                    342:     }
                    343:     code = (attr) ? CISTPL_DEVICE_GEO_A : CISTPL_DEVICE_GEO;
                    344:     has_geo = (read_tuple(handle, code, &geo) == CS_SUCCESS);
                    345:     if (has_geo && (device.ndev != geo.ngeo)) {
                    346: #ifdef PCMCIA_DEBUG
                    347:        printk(KERN_DEBUG "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_NULL) &&
                    355:            (device.dev[i].size != 0)) {
                    356:            r = kmalloc(sizeof(*r), GFP_KERNEL);
                    357:            r->region_magic = REGION_MAGIC;
                    358:            r->state = 0;
                    359:            r->dev_info[0] = '\0';
                    360:            r->mtd = NULL;
                    361:            r->info.Attributes = (attr) ? REGION_TYPE_AM : 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: 
                    392: static int match_region(client_handle_t handle, memory_handle_t list,
                    393:                        region_info_t *match)
                    394: {
                    395:     while (list != NULL) {
                    396:        if (!(handle->Attributes & INFO_MTD_CLIENT) ||
                    397:            (strcmp(handle->dev_info, list->dev_info) == 0)) {
                    398:            *match = list->info;
                    399:            return CS_SUCCESS;
                    400:        }
                    401:        list = list->info.next;
                    402:     }
                    403:     return CS_NO_MORE_ITEMS;
                    404: } /* match_region */
                    405: 
                    406: int get_first_region(client_handle_t handle, region_info_t *rgn)
                    407: {
                    408:     socket_info_t *s = SOCKET(handle);
                    409:     if (CHECK_HANDLE(handle))
                    410:        return CS_BAD_HANDLE;
                    411:     
                    412:     if ((handle->Attributes & INFO_MASTER_CLIENT) &&
                    413:        (!(s->state & SOCKET_REGION_INFO))) {
                    414:        setup_regions(handle, 0, &s->c_region);
                    415:        setup_regions(handle, 1, &s->a_region);
                    416:        s->state |= SOCKET_REGION_INFO;
                    417:     }
                    418: 
                    419:     if (rgn->Attributes & REGION_TYPE_AM)
                    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: 
                    425: int get_next_region(client_handle_t handle, region_info_t *rgn)
                    426: {
                    427:     if (CHECK_HANDLE(handle))
                    428:        return CS_BAD_HANDLE;
                    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: 
                    438: int 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))
                    444:        return CS_BAD_HANDLE;
                    445:     s = SOCKET(handle);
                    446:     if (reg->Attributes & REGION_TYPE_AM)
                    447:        list = s->a_region;
                    448:     else
                    449:        list = s->c_region;
                    450:     DEBUG(1, "cs: register_mtd(0x%p, '%s', 0x%x)\n",
                    451:          handle, handle->dev_info, reg->Offset);
                    452:     while (list) {
                    453:        if (list->info.CardOffset == reg->Offset) break;
                    454:        list = list->info.next;
                    455:     }
                    456:     if (list && (list->mtd == NULL) &&
                    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_SUCCESS;
                    463:     } else
                    464:        return CS_BAD_OFFSET;
                    465: } /* register_mtd */
                    466: 
                    467: /*======================================================================
                    468: 
                    469:     Erase queue management functions
                    470:     
                    471: ======================================================================*/
                    472: 
                    473: int register_erase_queue(client_handle_t *handle, eraseq_hdr_t *header)
                    474: {
                    475:     eraseq_t *queue;
                    476: 
                    477:     if ((handle == NULL) || CHECK_HANDLE(*handle))
                    478:        return CS_BAD_HANDLE;
                    479:     queue = kmalloc(sizeof(*queue), GFP_KERNEL);
                    480:     if (!queue) return CS_OUT_OF_RESOURCE;
                    481:     queue->eraseq_magic = ERASEQ_MAGIC;
                    482:     queue->handle = *handle;
                    483:     queue->count = header->QueueEntryCnt;
                    484:     queue->entry = header->QueueEntryArray;
                    485:     *handle = (client_handle_t)queue;
                    486:     return CS_SUCCESS;
                    487: } /* register_erase_queue */
                    488: 
                    489: int deregister_erase_queue(eraseq_handle_t eraseq)
                    490: {
                    491:     int i;
                    492:     if (CHECK_ERASEQ(eraseq))
                    493:        return CS_BAD_HANDLE;
                    494:     for (i = 0; i < eraseq->count; i++)
                    495:        if (ERASE_IN_PROGRESS(eraseq->entry[i].State)) break;
                    496:     if (i < eraseq->count)
                    497:        return CS_BUSY;
                    498:     eraseq->eraseq_magic = 0;
                    499:     kfree(eraseq);
                    500:     return CS_SUCCESS;
                    501: } /* deregister_erase_queue */
                    502: 
                    503: int check_erase_queue(eraseq_handle_t eraseq)
                    504: {
                    505:     int i;
                    506:     if (CHECK_ERASEQ(eraseq))
                    507:        return CS_BAD_HANDLE;
                    508:     for (i = 0; i < eraseq->count; i++)
                    509:        if (eraseq->entry[i].State == ERASE_QUEUED)
                    510:            setup_erase_request(eraseq->handle, &eraseq->entry[i]);
                    511:     return CS_SUCCESS;
                    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: 
                    521: int 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) || CHECK_HANDLE(*handle))
                    527:        return CS_BAD_HANDLE;
                    528:     s = SOCKET(*handle);
                    529:     if (open->Attributes & MEMORY_TYPE_AM)
                    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",
                    540:              handle, open->Offset, region);
                    541:        return CS_SUCCESS;
                    542:     } else
                    543:        return CS_BAD_OFFSET;
                    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: 
                    554: int close_memory(memory_handle_t handle)
                    555: {
                    556:     DEBUG(1, "cs: close_memory(0x%p)\n", handle);
                    557:     if (CHECK_REGION(handle))
                    558:        return CS_BAD_HANDLE;
                    559:     return CS_SUCCESS;
                    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: 
                    569: int read_memory(memory_handle_t handle, mem_op_t *req, caddr_t buf)
                    570: {
                    571:     mtd_request_t mtd;
                    572:     if (CHECK_REGION(handle))
                    573:        return CS_BAD_HANDLE;
                    574:     if (req->Offset >= handle->info.RegionSize)
                    575:        return CS_BAD_OFFSET;
                    576:     if (req->Offset+req->Count > handle->info.RegionSize)
                    577:        return CS_BAD_SIZE;
                    578:     
                    579:     mtd.SrcCardOffset = req->Offset + handle->info.CardOffset;
                    580:     mtd.TransferLength = req->Count;
                    581:     mtd.MediaID = handle->MediaID;
                    582:     mtd.Function = MTD_REQ_READ;
                    583:     if (req->Attributes & MEM_OP_BUFFER_KERNEL)
                    584:        mtd.Function |= MTD_REQ_KERNEL;
                    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: 
                    595: int write_memory(memory_handle_t handle, mem_op_t *req, caddr_t buf)
                    596: {
                    597:     mtd_request_t mtd;
                    598:     if (CHECK_REGION(handle))
                    599:        return CS_BAD_HANDLE;
                    600:     if (req->Offset >= handle->info.RegionSize)
                    601:        return CS_BAD_OFFSET;
                    602:     if (req->Offset+req->Count > handle->info.RegionSize)
                    603:        return CS_BAD_SIZE;
                    604:     
                    605:     mtd.DestCardOffset = req->Offset + handle->info.CardOffset;
                    606:     mtd.TransferLength = req->Count;
                    607:     mtd.MediaID = handle->MediaID;
                    608:     mtd.Function = MTD_REQ_WRITE;
                    609:     if (req->Attributes & MEM_OP_BUFFER_KERNEL)
                    610:        mtd.Function |= MTD_REQ_KERNEL;
                    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: 
                    620: int copy_memory(memory_handle_t handle, copy_op_t *req)
                    621: {
                    622:     if (CHECK_REGION(handle))
                    623:        return CS_BAD_HANDLE;
                    624:     return CS_UNSUPPORTED_FUNCTION;
                    625: }
                    626: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.