Annotation of drvEIDE/EIDE.drvproj/EIDE.lksproj/AtapiCntInternal.m, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.0 (the 'License').  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License."
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: /*
                     25:  * Copyright 1997-1998 by Apple Computer, Inc., All rights reserved.
                     26:  * Copyright 1994-1997 NeXT Software, Inc., All rights reserved.
                     27:  *
                     28:  * AtapiCntInternal.m - Implementation of ATAPI controller class.
                     29:  *
                     30:  *
                     31:  * HISTORY
                     32:  *
                     33:  * 05-Mar-1996  Rakesh Dubey at NeXT
                     34:  *     Modified so that no memory is allocated at run-time.
                     35:  *
                     36:  * 21-Mar-1995         Rakesh Dubey at NeXT 
                     37:  *     Created. 
                     38:  */
                     39: 
                     40: #import "IdeCnt.h"
                     41: #import "AtapiCntInternal.h"
                     42: #import <kern/assert.h>
                     43: #import <driverkit/kernelDriver.h>
                     44: #import <driverkit/interruptMsg.h>
                     45: #import <mach/mach_interface.h>
                     46: #import <driverkit/IODevice.h>
                     47: #import <machkit/NXLock.h>
                     48: #import <kernserv/prototypes.h>
                     49: 
                     50: /*
                     51:  * Top-level I/O thread.
                     52:  */
                     53: static volatile void atapiThread(AtapiController *atapiCnt);
                     54: 
                     55: @implementation AtapiController(Internal)
                     56: 
                     57: - initResources:direct
                     58: {
                     59: #ifdef NO_ATAPI_RUNTIME_MEMORY_ALLOCATION
                     60:     int i;
                     61:     atapiBuf_t *atapiBuf;
                     62: #endif NO_ATAPI_RUNTIME_MEMORY_ALLOCATION
                     63:        
                     64:     _ataController = direct;
                     65:     
                     66:     queue_init(&_ioQueueNodisk);
                     67:     
                     68: #ifdef NO_ATAPI_RUNTIME_MEMORY_ALLOCATION
                     69: 
                     70:     /* Set up a queue of ideBufs */
                     71:     queue_init(&_atapiBufQueue);
                     72:     _atapiBufLock = [NXLock new];
                     73:     [_atapiBufLock lock];
                     74:     
                     75:     for (i = 0; i < MAX_NUM_ATAPIBUF; i++)     {
                     76:        atapiBuf = &_atapiBufPool[i];
                     77:        atapiBuf->waitLock = [NXConditionLock alloc];
                     78:        [atapiBuf->waitLock initWith:NO];
                     79:        queue_enter(&_atapiBufQueue, atapiBuf, atapiBuf_t *, bufLink);
                     80:     }
                     81:     [_atapiBufLock unlock];
                     82:     
                     83:     if (_ide_debug)    {
                     84:        IOLog("NO_ATAPI_RUNTIME_MEMORY_ALLOCATION\n");
                     85:     }
                     86: 
                     87: #endif NO_ATAPI_RUNTIME_MEMORY_ALLOCATION
                     88: 
                     89:     _ioQLock = [NXConditionLock alloc];
                     90:     [_ioQLock initWith:NO_WORK_AVAILABLE];
                     91:     
                     92:     IOForkThread((IOThreadFunc)atapiThread, self);
                     93:     
                     94:     return self;
                     95: }
                     96: 
                     97: /*
                     98:  * Free up local resources. 
                     99:  */
                    100: - free
                    101: {
                    102:     /*
                    103:      * First kill the I/O thread, then free alloc'd instance variables. 
                    104:      */
                    105:     atapiBuf_t *atapiBuf;
                    106:     int i;
                    107: 
                    108:     atapiBuf = [self allocAtapiBuf];
                    109:     [self enqueueAtapiBuf:atapiBuf];
                    110:     
                    111:     [self freeAtapiBuf:atapiBuf];
                    112:     [_ioQLock free];
                    113: 
                    114: #ifdef NO_ATAPI_RUNTIME_MEMORY_ALLOCATION
                    115:     if (_atapiBufLock)
                    116:        [_atapiBufLock free];
                    117:     
                    118:     for (i = 0; i < MAX_NUM_ATAPIBUF; i++) {
                    119:        if (_atapiBufPool[i].waitLock)
                    120:            [_atapiBufPool[i].waitLock free];
                    121:     }
                    122: #endif NO_ATAPI_RUNTIME_MEMORY_ALLOCATION
                    123: 
                    124:     return ([super free]);
                    125: }
                    126: 
                    127: /*
                    128:  * Allocate and free AtapiBuf_t's.
                    129:  */
                    130: 
                    131: #ifdef NO_ATAPI_RUNTIME_MEMORY_ALLOCATION
                    132: - (atapiBuf_t *) allocAtapiBuf
                    133: {
                    134:     atapiBuf_t *atapiBuf;
                    135:     id waitLock;
                    136: 
                    137:     while (1)  {
                    138:        [_atapiBufLock lock];
                    139:        if (!queue_empty(&_atapiBufQueue))
                    140:            break;
                    141:        [_atapiBufLock unlock];
                    142:        IOSleep(20);            // the system is overloaded
                    143:     }
                    144:     
                    145:     ASSERT(queue_empty(&_atapiBufQueue) != 0);
                    146:     atapiBuf = (atapiBuf_t *) queue_first(&_atapiBufQueue);
                    147:     ASSERT(atapiBuf != 0);
                    148:     queue_remove(&_atapiBufQueue, atapiBuf, atapiBuf_t *, bufLink);
                    149: 
                    150:     waitLock = atapiBuf->waitLock;
                    151:     bzero(atapiBuf, sizeof(atapiBuf_t));
                    152:     atapiBuf->waitLock = waitLock;
                    153:     [atapiBuf->waitLock initWith:NO];
                    154:     
                    155:     [_atapiBufLock unlock];
                    156:     return (atapiBuf);
                    157: }
                    158: 
                    159: - (void)freeAtapiBuf:(atapiBuf_t *) atapiBuf
                    160: {
                    161:     [_atapiBufLock lock];
                    162:     queue_enter(&_atapiBufQueue, atapiBuf, atapiBuf_t *, bufLink);
                    163:     ASSERT(queue_empty(&_atapiBufQueue) != 0);
                    164:     [_atapiBufLock unlock];
                    165: }
                    166: 
                    167: #else NO_ATAPI_RUNTIME_MEMORY_ALLOCATION
                    168: 
                    169: - (atapiBuf_t *) allocAtapiBuf
                    170: {
                    171:     atapiBuf_t *atapiBuf = IOMalloc(sizeof(atapiBuf_t));
                    172: 
                    173:     bzero(atapiBuf, sizeof(atapiBuf_t));
                    174:     atapiBuf->waitLock = [NXConditionLock alloc];
                    175:     [atapiBuf->waitLock initWith:NO];
                    176:     
                    177:     return (atapiBuf);
                    178: }
                    179: 
                    180: - (void)freeAtapiBuf:(atapiBuf_t *) atapiBuf
                    181: {
                    182:     if (atapiBuf->waitLock) {
                    183:        [atapiBuf->waitLock free];
                    184:     }
                    185:     IOFree(atapiBuf, sizeof(atapiBuf_t));
                    186: }
                    187: #endif NO_ATAPI_RUNTIME_MEMORY_ALLOCATION
                    188: 
                    189: /*
                    190:  * -- Enqueue an AtapiBuf_t on ioQueue<Disk,Nodisk>
                    191:  * -- wake up the I/O thread
                    192:  * -- wait for I/O complete (if atapiBuf->pending == NULL)
                    193:  *
                    194:  * All I/O goes thru here; this is the last method called by exported methods
                    195:  * before the I/O thread takes over. 
                    196:  */
                    197: - (IOReturn) enqueueAtapiBuf:(atapiBuf_t *) atapiBuf
                    198: {
                    199:     queue_head_t *q;
                    200: 
                    201:     [_ioQLock lock];
                    202:     q = &_ioQueueNodisk;
                    203:     queue_enter(q, atapiBuf, atapiBuf_t *, link);
                    204:     [_ioQLock unlockWith:WORK_AVAILABLE];
                    205: 
                    206:     /*
                    207:      * Wait for I/O complete. 
                    208:      */
                    209:     [atapiBuf->waitLock lockWhen:YES];
                    210:     [atapiBuf->waitLock unlock];
                    211: 
                    212:     /* FIXME: What should this value be?? */
                    213:     return (atapiBuf->status);
                    214: }
                    215: 
                    216: 
                    217: /*
                    218:  * Either wake up the thread which is waiting on the ideCmdBuf, or send an 
                    219:  * ioComplete back to client. ideCmdBuf->status must be valid.
                    220:  */
                    221: - (void)atapiIoComplete:(atapiBuf_t *) atapiBuf
                    222: {
                    223:     /*
                    224:      * Sync I/O. Just wake up the waiting thread. 
                    225:      */
                    226:     [atapiBuf->waitLock lock];
                    227:     [atapiBuf->waitLock unlockWith:YES];
                    228: }
                    229: 
                    230: /*
                    231:  * Main command dispatch method. 
                    232:  */
                    233: - (void)atapiCmdDispatch:(atapiBuf_t *)atapiBuf
                    234: {
                    235:     switch (atapiBuf->command) {
                    236:     
                    237:                case ATAPI_CNT_IOREQ:
                    238:                        atapiBuf->status = [_ataController
                    239:                                atapiExecuteCmd:atapiBuf->atapiIoReq 
                    240:                                buffer:atapiBuf->buffer client:atapiBuf->client];
                    241:                        break;
                    242: 
                    243:                case ATAPI_CNT_THREAD_ABORT:
                    244: 
                    245:                        /*
                    246:                         * First give I/O complete before we die. 
                    247:                         */
                    248:                        atapiBuf->status = STAT_GOOD;
                    249:                        [self atapiIoComplete:atapiBuf];
                    250:                        IOExitThread();
                    251: 
                    252:                default:
                    253:                        IOLog("%s: Bogus atapiBuf->command 0x%0x in atapiCmdDispatch\n", 
                    254:                                [self name], atapiBuf->command);
                    255:                        IOPanic("atapiThread");
                    256:        }
                    257: 
                    258:     [self atapiIoComplete:atapiBuf];
                    259:     return;
                    260: }
                    261: 
                    262: /*
                    263:  * Unlock ioQLock, updating condition variable as appropriate.
                    264:  */
                    265: - (void)unlockIoQLock
                    266: {
                    267:     int     queue_state;
                    268: 
                    269:     if (!queue_empty(&_ioQueueNodisk))
                    270:        queue_state = WORK_AVAILABLE;
                    271:     else
                    272:        queue_state = NO_WORK_AVAILABLE;
                    273:     [_ioQLock unlockWith:queue_state];
                    274: }
                    275: 
                    276: 
                    277: @end
                    278: 
                    279: /*
                    280:  * I/O thread. Each one of these sits around waiting for work to do on 
                    281:  * ioQueue; when something appears, the thread grabs it and disptahes it.
                    282:  */
                    283: 
                    284: static volatile void
                    285: atapiThread(AtapiController *atapiCnt)
                    286: {
                    287:     atapiBuf_t *atapiBuf;
                    288:     queue_head_t *q;
                    289: 
                    290:     while (1) {
                    291: 
                    292:        /*
                    293:         * Wait for some work to do. 
                    294:         */
                    295:        [atapiCnt->_ioQLock lockWhen:WORK_AVAILABLE];
                    296: 
                    297:        /*
                    298:         * Service all requests which do not require a disk. 
                    299:         */
                    300:        q = &atapiCnt->_ioQueueNodisk;
                    301:        while (!queue_empty(q)) {
                    302:            atapiBuf = (atapiBuf_t *) queue_first(q);
                    303:            queue_remove(q, atapiBuf, atapiBuf_t *, link);
                    304:            [atapiCnt->_ioQLock unlock];
                    305:            [atapiCnt atapiCmdDispatch:atapiBuf];
                    306:            [atapiCnt->_ioQLock lock];
                    307:        }
                    308: 
                    309:        [atapiCnt unlockIoQLock];
                    310:     }
                    311: 
                    312:     /* NOT REACHED */
                    313: }

unix.superglobalmegacorp.com

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