Annotation of Gnu-Mach/linux/pcmcia-cs/modules/bulkmem.c, revision 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.