Annotation of driverkit/libDriver/eisa/IOEISADirectDevice.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 (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.