Annotation of driverkit/libDriver/eisa/IOEISADirectDevice.m, revision 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 (c) 1993 NeXT Computer, Inc.
        !            26:  *
        !            27:  * ISA/EISA direct device implementation.
        !            28:  *
        !            29:  * HISTORY
        !            30:  *
        !            31:  * 10Jan93 Brian Pinkerton at NeXT
        !            32:  *     Created.
        !            33:  *
        !            34:  *
        !            35:  *  TODO:
        !            36:  *     Implement IOPort reservation
        !            37:  *     Verify that host-master DMA is working with DavidS
        !            38:  */
        !            39: 
        !            40: #define KERNEL_PRIVATE 1
        !            41: 
        !            42: #import <objc/List.h>
        !            43: #import <driverkit/i386/directDevice.h>
        !            44: #import <driverkit/IODirectDevicePrivate.h>
        !            45: #import <driverkit/i386/IOEISADeviceDescription.h>
        !            46: #import <driverkit/driverTypes.h>
        !            47: #import <driverkit/i386/driverTypesPrivate.h>
        !            48: #import <driverkit/generalFuncs.h>
        !            49: #import <driverkit/i386/driverTypes.h>
        !            50: #import <driverkit/i386/EISAKernBus.h>
        !            51: #import <driverkit/KernDevice.h>
        !            52: #import <driverkit/KernDeviceDescription.h>
        !            53: #import <driverkit/kernelDriver.h>
        !            54: #import <driverkit/interruptMsg.h>
        !            55: #import <machdep/i386/dma_exported.h>
        !            56: #import <machdep/i386/dma.h>
        !            57: #import <machdep/i386/xpr.h>
        !            58: #import <machkit/NXLock.h>
        !            59: #import <kernserv/lock.h>
        !            60: #import <kernserv/prototypes.h>
        !            61: 
        !            62: #import <objc/HashTable.h>
        !            63: 
        !            64: extern NXLock  *dmaLock;       // in autoconf_i386.m
        !            65: 
        !            66: @interface IODirectDevice(EISAPrivate)
        !            67: 
        !            68: - (unsigned int) _localToChannel:(unsigned int) localChannel;
        !            69: - initEISA;
        !            70: - freeEISA;
        !            71: 
        !            72: @end
        !            73: 
        !            74: struct _eisa_private {
        !            75:     Arch       type;
        !            76: };
        !            77: 
        !            78: @implementation IODirectDevice(IOEISADirectDevice)
        !            79: 
        !            80: - initEISA
        !            81: {
        !            82:        struct _eisa_private    *private;
        !            83: 
        !            84:        private = _busPrivate = (void *)IOMalloc(sizeof (*private));
        !            85:        private->type = EISA;
        !            86:        
        !            87:        return self;
        !            88: }
        !            89: 
        !            90: - freeEISA
        !            91: {
        !            92:        struct _eisa_private    *private = _busPrivate;
        !            93:        
        !            94:        IOFree((void *)private, sizeof (*private));
        !            95:        
        !            96:        return self;
        !            97: }
        !            98: 
        !            99: /*
        !           100:  *  A bunch of convenient private API:
        !           101:  *
        !           102:  *  Map from local channel numbers to real ones, and from local IRQ numbers
        !           103:  *  to real ones.
        !           104:  */
        !           105: - (unsigned int) _localToChannel:(unsigned int) localChannel
        !           106: {
        !           107:        return [(IOEISADeviceDescription *)_deviceDescription channelList][localChannel];
        !           108: }
        !           109: 
        !           110: 
        !           111: /*
        !           112:  *  Routines for dealing with interrupts start here.
        !           113:  */
        !           114: 
        !           115: - (IOReturn) reserveInterrupt  : (unsigned int)localInterrupt
        !           116: {
        !           117:        return IO_R_SUCCESS;
        !           118: }
        !           119: 
        !           120: - (void) releaseInterrupt      : (unsigned int) localInterrupt
        !           121: {
        !           122: }
        !           123: 
        !           124: 
        !           125: 
        !           126: 
        !           127: /*
        !           128:  *  The subclass overrides this method.  In the superclass, we just
        !           129:  *  return NO.
        !           130:  */
        !           131: - (BOOL) getHandler:(IOEISAInterruptHandler *)handler
        !           132:               level:(unsigned int *)ipl
        !           133:           argument:(unsigned int *) arg
        !           134:        forInterrupt:(unsigned int) localInterrupt
        !           135: {
        !           136:        return NO;
        !           137: }
        !           138: 
        !           139: 
        !           140: - (IOReturn) reserveChannel    : (unsigned int) localChannel
        !           141: {
        !           142:        return IO_R_SUCCESS;
        !           143: }
        !           144: 
        !           145: - (void) releaseChannel                : (unsigned int) localChannel
        !           146: {
        !           147: }
        !           148: 
        !           149: - (IOReturn) enableChannel:(unsigned int) localChannel
        !           150: {
        !           151:        unsigned int realChannel;
        !           152:        
        !           153:        if (localChannel >= [(IOEISADeviceDescription *)_deviceDescription numChannels])
        !           154:                return IO_R_INVALID_ARG;
        !           155: 
        !           156:        realChannel = [self _localToChannel:localChannel];
        !           157: 
        !           158:        dma_unmask_chan(realChannel);
        !           159:        return IO_R_SUCCESS;
        !           160: }
        !           161: 
        !           162: 
        !           163: - (void) disableChannel:(unsigned int) localChannel
        !           164: {
        !           165:        unsigned int realChannel;
        !           166:        
        !           167:        if (localChannel >= [(IOEISADeviceDescription *)_deviceDescription numChannels])
        !           168:                return;
        !           169: 
        !           170:        realChannel = [self _localToChannel:localChannel];
        !           171: 
        !           172:        dma_mask_chan(realChannel);
        !           173: }
        !           174: 
        !           175: 
        !           176: - (IOReturn) setTransferMode   : (IODMATransferMode) mode 
        !           177:                     forChannel : (unsigned int) localChannel;
        !           178: {
        !           179:        int real_mode;
        !           180:        unsigned int realChannel;
        !           181:        
        !           182:        if (localChannel >= [(IOEISADeviceDescription *)_deviceDescription numChannels])
        !           183:                return IO_R_INVALID_ARG;
        !           184: 
        !           185:        realChannel = [self _localToChannel:localChannel];
        !           186: 
        !           187:        switch(mode) {
        !           188:            case IO_Demand:
        !           189:                real_mode = DMA_MODE_DEMAND;
        !           190:                break;
        !           191:            case IO_Single:
        !           192:                real_mode = DMA_MODE_SINGLE;
        !           193:                break;
        !           194:            case IO_Block:
        !           195:                real_mode = DMA_MODE_BLOCK;
        !           196:                break;
        !           197:            case IO_Cascade:
        !           198:                real_mode = DMA_MODE_CASCADE;
        !           199:                break;
        !           200:        }
        !           201:        dma_chan_xfer_mode(realChannel, real_mode);
        !           202:        return IO_R_SUCCESS;
        !           203: }
        !           204: 
        !           205: /*
        !           206:  * Enable/disable autoinitialize DMA mode. Default is 
        !           207:  * disabled.
        !           208:  */
        !           209: - (IOReturn)setAutoinitialize          : (BOOL)flag
        !           210:                     forChannel         : (unsigned)localChannel
        !           211: {
        !           212:        unsigned int realChannel;
        !           213:        
        !           214:        if (localChannel >= [(IOEISADeviceDescription *)_deviceDescription numChannels])
        !           215:                return IO_R_INVALID_ARG;
        !           216: 
        !           217:        realChannel = [self _localToChannel:localChannel];
        !           218: 
        !           219:        dma_chan_autoinit(realChannel, (flag ? 1 : 0));
        !           220:        return IO_R_SUCCESS;
        !           221: }
        !           222: 
        !           223: /*
        !           224:  * Set DMA address increment/decrement mode.
        !           225:  * Default is IO_Increment.
        !           226:  */
        !           227: - (IOReturn)setIncrementMode           : (IOIncrementMode)mode
        !           228:                     forChannel         : (unsigned)localChannel
        !           229: {
        !           230:        unsigned int realChannel;
        !           231:        int dir;
        !           232:        
        !           233:        if(mode == IO_Decrement) {
        !           234:                return IO_R_UNSUPPORTED;                // nope!
        !           235:        }
        !           236:        if (localChannel >= [(IOEISADeviceDescription *)_deviceDescription numChannels])
        !           237:                return IO_R_INVALID_ARG;
        !           238: 
        !           239:        realChannel = [self _localToChannel:localChannel];
        !           240: 
        !           241:        dir = (mode == IO_Decrement ? DMA_ADRS_DECR : DMA_ADRS_INCR);
        !           242:        dma_chan_adrs_dir(realChannel, dir);
        !           243:        return IO_R_SUCCESS;
        !           244: }
        !           245: 
        !           246: 
        !           247: /*
        !           248:  *  Returns a DMA buffer for the contents of physical memory starting at
        !           249:  *  addr and continuing for length bytes.  If the physical address changed
        !           250:  *  to accommodate the ISA bus, the new physical address is returned in
        !           251:  *  place.  The DMABuffer is an opaque type.
        !           252:  *
        !           253:  *  Warning: this method allocates memory, so it can block!
        !           254:  */
        !           255: - (IOEISADMABuffer) createDMABufferFor:(unsigned int *) physAddr
        !           256:                         length:(unsigned int) length
        !           257:                         read:(BOOL) isRead
        !           258:                         needsLowMemory:(BOOL) lowerMem
        !           259:                         limitSize:(BOOL) limitSize
        !           260: {
        !           261:        dma_xfer_t *xfer = IOMalloc(sizeof(dma_xfer_t));
        !           262: 
        !           263:        if (xfer == NULL)
        !           264:                return NULL;
        !           265: 
        !           266:        xfer->phys = *physAddr;
        !           267:        xfer->len = length;
        !           268:        xfer->read = isRead;
        !           269:        xfer->lower16 = lowerMem;
        !           270:        xfer->bound64 = limitSize;
        !           271:        xfer->buffered = FALSE;
        !           272: 
        !           273:        if (!dma_xfer(xfer, physAddr)) {
        !           274:                xpr_dmabuf("createDMABufferFor: dma_xfer() failed; physAddr"
        !           275:                        "0x%x\n", physAddr, 2,3,4,5);
        !           276:                IOFree(xfer, sizeof(dma_xfer_t));
        !           277:                return NULL;
        !           278:        }
        !           279:        
        !           280:        xpr_dmabuf("createDMABufferFor: xfer 0x%x\n", xfer, 2,3,4,5);
        !           281:        return (IOEISADMABuffer) xfer;
        !           282: }
        !           283: 
        !           284: 
        !           285: - (void) freeDMABuffer:(IOEISADMABuffer) dmaBuffer
        !           286: {
        !           287:        dma_xfer_t *xfer = (dma_xfer_t *) dmaBuffer;
        !           288:        
        !           289:        xpr_dmabuf("freeDMABuffer: dmaBuffer active %d 0x%x\n", 
        !           290:                xfer, xfer->active,3,4,5);
        !           291:        if (xfer->active)
        !           292:                dma_xfer_done(xfer);
        !           293:        IOFree(xfer, sizeof(dma_xfer_t));
        !           294: }
        !           295: 
        !           296: 
        !           297: - (void) abortDMABuffer:(IOEISADMABuffer) dmaBuffer
        !           298: {
        !           299:        dma_xfer_t *xfer = (dma_xfer_t *) dmaBuffer;
        !           300:        
        !           301:        xpr_dmabuf("abortDMABuffer: dmaBuffer active %d 0x%x\n", 
        !           302:                xfer, xfer->active,3,4,5);
        !           303:        if (xfer->active)
        !           304:                dma_xfer_abort(xfer);
        !           305:        IOFree(xfer, sizeof(dma_xfer_t));
        !           306: }
        !           307: 
        !           308: - (IOReturn) startDMAForBuffer:(IOEISADMABuffer) buffer channel:(unsigned int) localChannel
        !           309: {
        !           310:        unsigned int realChannel;
        !           311:        
        !           312:        if (localChannel >= [(IOEISADeviceDescription *)_deviceDescription numChannels])
        !           313:                return IO_R_INVALID_ARG;
        !           314: 
        !           315:        realChannel = [self _localToChannel:localChannel];
        !           316: 
        !           317:        if (dma_xfer_chan(realChannel, (dma_xfer_t *) buffer))
        !           318:                return IO_R_SUCCESS;
        !           319:        else
        !           320:                return IO_R_NO_FRAMES;                  /* XXX */
        !           321: }
        !           322: 
        !           323: /*
        !           324:  * Return localChannel's current address and count.
        !           325:  */
        !           326: - (unsigned)currentAddressForChannel   : (unsigned)localChannel
        !           327: {
        !           328:        unsigned int realChannel;
        !           329:        
        !           330:        if (localChannel >= [(IOEISADeviceDescription *)_deviceDescription numChannels])
        !           331:                return 0;
        !           332:        realChannel = [self _localToChannel:localChannel];
        !           333:        return(get_dma_addr(realChannel));
        !           334: }
        !           335: 
        !           336: - (unsigned)currentCountForChannel     : (unsigned)localChannel
        !           337: {
        !           338:        unsigned int realChannel;
        !           339:        
        !           340:        if (localChannel >= [(IOEISADeviceDescription *)_deviceDescription numChannels])
        !           341:                return 0;
        !           342:        realChannel = [self _localToChannel:localChannel];
        !           343:        return(get_dma_count(realChannel));
        !           344: }
        !           345: 
        !           346: 
        !           347: - (BOOL) isDMADone:(unsigned int) localChannel
        !           348: {
        !           349:        if (localChannel >= [(IOEISADeviceDescription *)_deviceDescription numChannels])
        !           350:                return NO;
        !           351: 
        !           352:        return (is_dma_done([self _localToChannel:localChannel]) ?
        !           353:                YES : NO);
        !           354: }
        !           355: 
        !           356: 
        !           357: 
        !           358: 
        !           359: /*
        !           360:  * Determine whether or not the aassociated device is connected to an EISA 
        !           361:  * bus. Returns YES if so, else returns NO.
        !           362:  */
        !           363: extern BOOL is_ISA;            // in driverkit/i386/autoconf_i386.m
        !           364: 
        !           365: - (BOOL)isEISAPresent
        !           366: {
        !           367:        return (is_ISA ? NO : YES);
        !           368: }
        !           369: 
        !           370: - (BOOL)getEISAId: (unsigned int *)_id  forSlot: (int) slot
        !           371: {
        !           372:        return eisa_id(slot, _id);
        !           373: }
        !           374: 
        !           375: /*
        !           376:  * DMA lock package. 
        !           377:  */
        !           378:  
        !           379: typedef struct _dmaQueueEntry dmaQueueEntry;
        !           380: struct _dmaQueueEntry {
        !           381:        id              device;
        !           382:        int             count;
        !           383:        dmaQueueEntry   *next;
        !           384: };
        !           385: 
        !           386: static dmaQueueEntry *dmaQueueHead;
        !           387: static dmaQueueEntry *dmaQueueTail;
        !           388: static int sleepChannel;                       // for sleep/wakeup
        !           389: static simple_lock_t dmaSpinLock;              // ditto
        !           390: 
        !           391: int dmaLockDisable = 0;
        !           392: 
        !           393: extern void thread_wakeup(int x);
        !           394: 
        !           395: /*
        !           396:  * Init routine, called out from dev_server_init().
        !           397:  */
        !           398: void initDmaLock()
        !           399: {
        !           400:        dmaQueueHead = NULL;
        !           401:        dmaQueueTail = NULL;
        !           402:        dmaSpinLock  = simple_lock_alloc();
        !           403:        simple_lock_init(dmaSpinLock);
        !           404: }
        !           405: 
        !           406: /*
        !           407:  * Sleep until specified dmaQueueEntry is at the head of dmaQueue.
        !           408:  * Note we have to wait for a specific dmaQueueEntry to bubble to the head,
        !           409:  * not just any dmaQueueEntry for a specific device, since one device can have 
        !           410:  * one entry at the head and another somewhere back in line. 
        !           411:  *
        !           412:  * dmaSpinLock held on entry and exit.
        !           413:  */
        !           414: static void waitTilHead(dmaQueueEntry *queueEntry)
        !           415: {
        !           416:        while(queueEntry != dmaQueueHead) {
        !           417:                thread_sleep((int)&sleepChannel, dmaSpinLock, FALSE); 
        !           418:                simple_lock(dmaSpinLock);
        !           419:        }
        !           420: }
        !           421: 
        !           422: /*
        !           423:  * Cons up a new dmaQueueEntry, count of 1, for specified device.
        !           424:  */
        !           425: static inline dmaQueueEntry *queueEntryAlloc(id device)
        !           426: {
        !           427:        dmaQueueEntry *queueEntry = IOMalloc(sizeof(dmaQueueEntry));
        !           428:        
        !           429:        queueEntry->count  = 1;
        !           430:        queueEntry->device = device;
        !           431:        queueEntry->next   = NULL;
        !           432:        return queueEntry;
        !           433: }
        !           434: 
        !           435: /*
        !           436:  * Free a dmaQueueEntry.
        !           437:  */
        !           438: static inline void queueEntryFree(dmaQueueEntry *queueEntry)
        !           439: {
        !           440:        ASSERT(queueEntry->count == 0);
        !           441:        IOFree(queueEntry, sizeof(dmaQueueEntry));
        !           442: }
        !           443: 
        !           444: /*
        !           445:  * Acquire dma lock. Allows multiple threads associated with one device
        !           446:  * instance to hold the DMA lock siimultaneously. If calling device
        !           447:  * owns the lock but other devices are blocked waiting for it, calling 
        !           448:  * thread will block, and will not acquire the lock until all other pending
        !           449:  * requests are honored.
        !           450:  */
        !           451: - (void)reserveDMALock
        !           452: {
        !           453:        dmaQueueEntry *queueEntry;
        !           454:        dmaQueueEntry *newQueueEntry;
        !           455:        
        !           456:        if([self isEISAPresent] || dmaLockDisable) {
        !           457:                return;
        !           458:        }
        !           459:        newQueueEntry = queueEntryAlloc(self);
        !           460:        simple_lock(dmaSpinLock);
        !           461:        if(dmaQueueHead == NULL) {
        !           462:                /*
        !           463:                 * Trivial quiescent case.
        !           464:                 */
        !           465:                dmaQueueHead = dmaQueueTail = newQueueEntry;
        !           466:                simple_unlock(dmaSpinLock);
        !           467:                return;
        !           468:        }
        !           469:        queueEntry = dmaQueueHead;
        !           470:        if((queueEntry->device == self) && (queueEntry->next == NULL)) {
        !           471:                /*
        !           472:                 * This device owns the lock, and no other requests pending.
        !           473:                 */
        !           474:                queueEntry->count++;
        !           475:                simple_unlock(dmaSpinLock);
        !           476:                queueEntryFree(newQueueEntry);
        !           477:                return;
        !           478:        }
        !           479:        
        !           480:        /*
        !           481:         * See if any subsequent entries (after the first one) match this
        !           482:         * device.
        !           483:         */
        !           484:        queueEntry = queueEntry->next;
        !           485:        while(queueEntry) {
        !           486:                if(queueEntry->device == self) {
        !           487:                        /*
        !           488:                         * Calling device has a request pending, not at head 
        !           489:                         * of queue. Lump these together.
        !           490:                         */
        !           491:                        queueEntry->count++;
        !           492:                        waitTilHead(queueEntry);
        !           493:                        simple_unlock(dmaSpinLock);
        !           494:                        queueEntryFree(newQueueEntry);
        !           495:                        return;
        !           496:                }
        !           497:                queueEntry = queueEntry->next;
        !           498:        }
        !           499:        
        !           500:        /*
        !           501:         * New request for this device.
        !           502:         */
        !           503:        dmaQueueTail->next = newQueueEntry;
        !           504:        dmaQueueTail = newQueueEntry;
        !           505:        waitTilHead(newQueueEntry);
        !           506:        simple_unlock(dmaSpinLock);
        !           507:        return;
        !           508: }
        !           509: 
        !           510: - (void)releaseDMALock
        !           511: {
        !           512:        dmaQueueEntry *queueEntry = dmaQueueHead;
        !           513:        dmaQueueEntry *freeQueueEntry = NULL;
        !           514:        boolean_t needWakeup = FALSE;
        !           515:        
        !           516:        if([self isEISAPresent] || dmaLockDisable) {
        !           517:                return;
        !           518:        }
        !           519:        simple_lock(dmaSpinLock);
        !           520:        if(queueEntry->device != self) {
        !           521:                simple_unlock(dmaSpinLock);
        !           522:                IOLog("%s: releaseDmaLock when not holding lock\n", 
        !           523:                        [self name]);
        !           524:                panic("releaseDMALock");
        !           525:        }
        !           526:        if(--queueEntry->count == 0) {
        !           527:                /*
        !           528:                 * This device is done. Wake up others, if any.
        !           529:                 */
        !           530:                needWakeup = (queueEntry->next != NULL);
        !           531:                freeQueueEntry = queueEntry;
        !           532:                dmaQueueHead = queueEntry->next;
        !           533:        }
        !           534:        simple_unlock(dmaSpinLock);
        !           535:        if(needWakeup) {
        !           536:                thread_wakeup((int)&sleepChannel);
        !           537:        }
        !           538:        if(freeQueueEntry != NULL) {
        !           539:                queueEntryFree(freeQueueEntry);
        !           540:        }
        !           541: }
        !           542: 
        !           543: /*
        !           544:  * Support for the extended mode register (EISA only).
        !           545:  */
        !           546: 
        !           547: - (IOReturn)setDMATransferWidth        : (IOEISADMATransferWidth)width
        !           548:                      forChannel : (unsigned)localChannel
        !           549: {
        !           550:        unsigned int realChannel;
        !           551:        int dmaWidth;
        !           552:        
        !           553:        if((width == IO_16BitWordCount) || is_ISA) {
        !           554:                return IO_R_UNSUPPORTED;
        !           555:        }
        !           556:        if (localChannel >= [[self deviceDescription] numChannels]) {
        !           557:                return IO_R_INVALID_ARG;
        !           558:        }
        !           559:        realChannel = [self _localToChannel:localChannel];
        !           560: 
        !           561:        switch(width) {
        !           562:            case IO_8Bit:
        !           563:                dmaWidth = DMA_XFR_8_BIT;
        !           564:                break;
        !           565:            case IO_16BitWordCount:
        !           566:                dmaWidth = DMA_XFR_16_BIT_WORD;
        !           567:                break;
        !           568:            case IO_16BitByteCount:
        !           569:                dmaWidth = DMA_XFR_16_BIT_BYTE;
        !           570:                break;
        !           571:            case IO_32Bit:
        !           572:                dmaWidth = DMA_XFR_32_BIT;
        !           573:                break;
        !           574:            default:
        !           575:                return IO_R_INVALID_ARG;
        !           576:        }
        !           577:        dma_xfer_width(realChannel, dmaWidth);
        !           578:        return IO_R_SUCCESS;
        !           579: }
        !           580: 
        !           581: - (IOReturn)getDMATransferWidth        : (IOEISADMATransferWidth *)width_p
        !           582:                      forChannel : (unsigned)localChannel
        !           583: {
        !           584:        unsigned int realChannel;
        !           585:        int width;
        !           586:        
        !           587:        if (localChannel >= [[self deviceDescription] numChannels]) {
        !           588:                return IO_R_INVALID_ARG;
        !           589:        }
        !           590:        realChannel = [self _localToChannel:localChannel];
        !           591: 
        !           592:        width = get_dma_xfer_width(realChannel);
        !           593:        switch(width) {
        !           594:            case DMA_XFR_8_BIT:
        !           595:                *width_p = IO_8Bit;
        !           596:                break;
        !           597:            case DMA_XFR_16_BIT_WORD:
        !           598:                *width_p = IO_16BitWordCount;
        !           599:                break;
        !           600:            case DMA_XFR_16_BIT_BYTE:
        !           601:                *width_p = IO_16BitByteCount;
        !           602:                break;
        !           603:            case DMA_XFR_32_BIT:
        !           604:                *width_p = IO_32Bit;
        !           605:                break;
        !           606:            default:    /* should never be reached */
        !           607:                return IO_R_NOT_ATTACHED;
        !           608:        }
        !           609:        return IO_R_SUCCESS;
        !           610: }
        !           611: 
        !           612: /*
        !           613:  * Select DMA Timing.
        !           614:  */
        !           615: - (IOReturn)setDMATiming       : (IOEISADMATiming)timing
        !           616:                      forChannel : (unsigned)localChannel
        !           617: {
        !           618:        unsigned int realChannel;
        !           619:        int dmaTiming;
        !           620:        
        !           621:        if(is_ISA) {
        !           622:                return IO_R_UNSUPPORTED;
        !           623:        }
        !           624:        if (localChannel >= [[self deviceDescription] numChannels]) {
        !           625:                return IO_R_INVALID_ARG;
        !           626:        }
        !           627:        realChannel = [self _localToChannel:localChannel];
        !           628: 
        !           629:        switch(timing) {
        !           630:            case IO_Compatible:
        !           631:                dmaTiming = DMA_TIMING_COMPAT;
        !           632:                break;
        !           633:            case IO_TypeA:
        !           634:                dmaTiming = DMA_TIMING_A;
        !           635:                break;
        !           636:            case IO_TypeB:
        !           637:                dmaTiming = DMA_TIMING_B;
        !           638:                break;
        !           639:            case IO_Burst:
        !           640:                dmaTiming = DMA_TIMING_BURST;
        !           641:                break;
        !           642:        }
        !           643:        dma_timing(realChannel, dmaTiming);
        !           644:        return IO_R_SUCCESS;
        !           645: }
        !           646: 
        !           647: /*
        !           648:  * Select whether EOP pin is output (default) or input.
        !           649:  */
        !           650: - (IOReturn)setEOPAsOutput     : (BOOL)flag
        !           651:                      forChannel        : (unsigned)localChannel
        !           652: {
        !           653:        unsigned realChannel;
        !           654:        unsigned dmaFlag;
        !           655:        
        !           656:        if(is_ISA) {
        !           657:                return IO_R_UNSUPPORTED;
        !           658:        }
        !           659:        if (localChannel >= [[self deviceDescription] numChannels]) {
        !           660:                return IO_R_INVALID_ARG;
        !           661:        }
        !           662:        realChannel = [self _localToChannel:localChannel];
        !           663: 
        !           664:        dmaFlag = (flag ? DMA_EOP_OUT : DMA_EOP_IN);
        !           665:        dma_eop_in(realChannel, dmaFlag);
        !           666:        return IO_R_SUCCESS;
        !           667: }
        !           668: 
        !           669: /*
        !           670:  * Enable Stop register. Default is disabled; enabling this feature
        !           671:  * is not supported in [PR2]the current release.
        !           672:  */
        !           673: - (IOReturn)setStopRegisterMode : (IOEISAStopRegisterMode)mode
        !           674:                     forChannel         : (unsigned)localChannel
        !           675: {
        !           676:        unsigned realChannel;
        !           677:        unsigned dmaFlag;
        !           678:        
        !           679:        if((mode == IO_StopRegisterEnable) || is_ISA) {
        !           680:                return IO_R_UNSUPPORTED;
        !           681:        }
        !           682:        if (localChannel >= [[self deviceDescription] numChannels]) {
        !           683:                return IO_R_INVALID_ARG;
        !           684:        }
        !           685:        realChannel = [self _localToChannel:localChannel];
        !           686: 
        !           687:        if(mode == IO_StopRegisterEnable) {
        !           688:                dmaFlag = DMA_STOP_ENABLE;
        !           689:        }
        !           690:        else {
        !           691:                dmaFlag = DMA_STOP_DISABLE;
        !           692:        }
        !           693:        dma_stop_enable(realChannel, dmaFlag);
        !           694:        return IO_R_SUCCESS;
        !           695: }
        !           696: 
        !           697: - (IOReturn) reservePortRange  : (unsigned int) localPortRange
        !           698: {
        !           699:        return IO_R_SUCCESS;
        !           700: }
        !           701: 
        !           702: - (void) releasePortRange      : (unsigned int) localPortRange
        !           703: {
        !           704: }
        !           705: 
        !           706: @end

unix.superglobalmegacorp.com

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