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

unix.superglobalmegacorp.com

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