File:  [Apple Darwin 0.x] / driverkit / libDriver / eisa / IOEISADMATransferBuffer.m
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:37:51 2018 UTC (8 years, 2 months ago) by root
Branches: MAIN, Apple
CVS tags: HEAD, Darwin03, Darwin02
Darwin 0.2 Driver Kit

/*
 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
 * Reserved.  This file contains Original Code and/or Modifications of
 * Original Code as defined in and that are subject to the Apple Public
 * Source License Version 1.1 (the "License").  You may not use this file
 * except in compliance with the License.  Please obtain a copy of the
 * License at http://www.apple.com/publicsource and read it before using
 * this file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
/*
 * Copyright 1994 NeXT Computer, Inc.
 * All rights reserved.
 *
 */

#if NOTYET

#import <driverkit/i386/IOEISADMATransferBuffer.h>
#import <driverkit/IODeviceDescriptionPrivate.h>
#import <machdep/i386/dma.h>
#import <machdep/i386/dma_inline.h>
#import <machdep/i386/dma_exported.h>

#define MIN(a,b) ((a) < (b) ? (a) : (b))

@implementation IOEISADMATransferBuffer


-setChannel:(unsigned int)newChannel
 forDevice:device
{
    unsigned int *list;

    localChannel = newChannel;
    directDevice = device;
    deviceDescription = [device deviceDescription];
    if (deviceDescription == nil) {
	return nil;
    }
    if ((list = [deviceDescription channelList])) {
	realChannel = list[newChannel];
    } else {
	return nil;
    }
    return self;
}

-(IODMADirection)transferDirection
{
    return transferDirection;
}

-(void)setTransferDirection:(IODMADirection)dir
{
    transferDirection = dir;
}

-(IOReturn)startTransfer
{
    IORange range;
    
    range.start = 0;
    range.size = [self size];
    return [self startTransferAt:range];
}

-(IOReturn)startTransferAt:(IORange)range
{
    int Size;
    IOPhysicalRange prange;
    
    Size = [self size];
    if (range.start > Size || (range.start + range.size) > Size)
	return IO_R_INVALID;

    if ([self getPhysicalAddress:&prange at:range.start]
	    == NO) {
	return IO_R_INVALID;
    }
    prange.size = MIN(range.size, prange.size);
    
    (void) dma_mask_chan(realChannel);
    if (transferDirection == IO_DMARead) {
	/* DMA write to memory */
	dma_chan_xfer_dir(realChannel, DMA_XFER_WRITE);
    } else {
	/* DMA read from memory */
	dma_chan_xfer_dir(realChannel, DMA_XFER_READ);
    }

    dma_set_chan_addr(realChannel, prange.start);

    dma_set_chan_count(realChannel, prange.size);

    currentTransfer = prange;
    
    (void) dma_unmask_chan(realChannel);

    return (IO_R_SUCCESS);
}

-(IOReturn)abortTransfer
{
    // XXX
    return (IO_R_SUCCESS);
}

-(BOOL)transferIsComplete
{
    return is_dma_done(realChannel);
}

-(unsigned)currentTransferLocation
{
    return get_dma_addr(realChannel) - currentTransfer.start;
}

-(unsigned)currentTransferCount
{
    return get_dma_count(realChannel);
}


-(IOReturn)enableChannel
{
    dma_unmask_chan(realChannel);
    return IO_R_SUCCESS;
}
-(void)disableChannel
{
    dma_mask_chan(realChannel);
}


/*
 * Reserve and release exclusive DMA lock. Use is optional; provides
 * exclusion between mutually incompatible DMA devices.
 */
- (void)reserveDMALock
{
    [directDevice reserveDMALock];
}
- (void)releaseDMALock
{
    [directDevice releaseDMALock];
}

/*
 * FIXME -- the kernel dma code should provide a way
 * to get the current transfer mode.
 */

static IODMATransferMode currentMode;

-(IODMATransferMode)transferMode
{
    return currentMode;
}

-(IOReturn)setTransferMode:(IODMATransferMode)mode
{
    unsigned real_mode;
    
    switch(mode) {
    case IO_Demand:
	real_mode = DMA_MODE_DEMAND;
	break;
    case IO_Single:
    default:
	real_mode = DMA_MODE_SINGLE;
	break;
    case IO_Block:
	real_mode = DMA_MODE_BLOCK;
	break;
    case IO_Cascade:
	real_mode = DMA_MODE_CASCADE;
	break;
    }
    dma_chan_xfer_mode(realChannel, real_mode);
    currentMode = mode;
    return IO_R_SUCCESS;
}

-(IOEISADMATransferWidth)transferWidth
{
    int width;
    IOEISADMATransferWidth ret;
    
    width = get_dma_xfer_width(realChannel);
    switch(width) {
    case DMA_XFR_8_BIT:
    default:	/* should never be reached */
	ret = IO_8Bit;
	break;
    case DMA_XFR_16_BIT_WORD:
	ret = IO_16BitWordCount;
	break;
    case DMA_XFR_16_BIT_BYTE:
	ret = IO_16BitByteCount;
	break;
    case DMA_XFR_32_BIT:
	ret = IO_32Bit;
	break;
    }
    return ret;
}

-(IOReturn)setTransferWidth:(IOEISADMATransferWidth)width
{
    int dmaWidth;
    
    switch(width) {
    case IO_8Bit:
	dmaWidth = DMA_XFR_8_BIT;
	break;
    case IO_16BitWordCount:
	dmaWidth = DMA_XFR_16_BIT_WORD;
	break;
    case IO_16BitByteCount:
	dmaWidth = DMA_XFR_16_BIT_BYTE;
	break;
    case IO_32Bit:
	dmaWidth = DMA_XFR_32_BIT;
	break;
    default:
	return IO_R_INVALID_ARG;
    }
    dma_xfer_width(realChannel, dmaWidth);
    return IO_R_SUCCESS;
}

-(IOEISADMATiming)transferTiming
{
    return 0; //XXX
}

-(IOReturn)setTransferTiming:(IOEISADMATiming)timing
{
    int dmaTiming;
    
    switch(timing) {
    case IO_Compatible:
	dmaTiming = DMA_TIMING_COMPAT;
	break;
    case IO_TypeA:
	dmaTiming = DMA_TIMING_A;
	break;
    case IO_TypeB:
	dmaTiming = DMA_TIMING_B;
	break;
    case IO_Burst:
	dmaTiming = DMA_TIMING_BURST;
	break;
    }
    dma_timing(realChannel, dmaTiming);
    return IO_R_SUCCESS;
}

-(IOEISAStopRegisterMode)stopRegisterMode
{
    return 0; //XXX
}

-(IOReturn)setStopRegisterMode:(IOEISAStopRegisterMode)mode
{
    unsigned dmaFlag;
    
    if(mode == IO_StopRegisterEnable) {
	    dmaFlag = DMA_STOP_ENABLE;
    }
    else {
	    dmaFlag = DMA_STOP_DISABLE;
    }
    dma_stop_enable(realChannel, dmaFlag);
    return IO_R_SUCCESS;
}

-(IOIncrementMode)transferIncrementMode
{
    return 0; //XXX
}
-(IOReturn)setTransferIncrementMode:(IOIncrementMode)mode
{
    int dir = (mode == IO_Decrement ? DMA_ADRS_DECR : DMA_ADRS_INCR);

    dma_chan_adrs_dir(realChannel, dir);
    return IO_R_SUCCESS;
}

-(BOOL)autoinitializeMode
{
    return 0; //XXX
}

-(IOReturn)setAutoinitializeMode:(BOOL)mode
{
    dma_chan_autoinit(realChannel, (mode ? 1 : 0));
    return IO_R_SUCCESS;
}

-(BOOL)isValidForDMA
{
    int offset, total;
    IOPhysicalRange prange;
    
    if (eisa_present())
	return YES;

    for (total = [self size], offset = 0; total > 0; ) {
	if ([self getPhysicalAddress:&prange at:offset] == NO) {
	    return NO;
	}
	if (prange.start >= 16 * 1024 * 1024)	// XXX use symbolic constant
	    return NO;
	total -= prange.size;
	offset += prange.size;
    }
    return YES;
}


/*
 * Returns the maximum number of bytes that can be transferred in one
 * operation from the specified offset in the buffer.
 */
-(unsigned int)maximumTransferLengthAtOffset:(unsigned int)offset
{
    int len = 0;
    IOPhysicalRange prange;
    
    if ([self getPhysicalAddress:&prange at:offset] == NO)
	return 0;
    if (eisa_present())
	return prange.size;
    else
	return MIN(prange.size, 64 * 1024);
}

+(BOOL)allocMemoryWithSize:(int)memSize
       attributes:(IOBufferAttributes)attr
       alignment:(IOAlignment)align
       allocedAddress:(IOVirtualAddress *)allocPtr
       dataAddress:(IOVirtualAddress *)dataPtr
       allocedSize:(int *)sizePtr
       newAttributes:(IOBufferAttributes *)newAttrPtr
       newMap:(IOAddressMap *)mapPtr
{
    IOVirtualAddress vaddr;
    int alignSize, newSize;
    
    alignSize = IOAlignmentToSize(align);
    newSize = memSize + 2 * alignSize;
    
    /* an optimization that relies on IOMalloc returning aligned pages. */
    if (newSize > PAGE_SIZE && memSize <= PAGE_SIZE)
	newSize = PAGE_SIZE;
    
    if (eisa_present())
	vaddr = (IOVirtualAddress)IOMalloc(newSize);
    else
	vaddr = (IOVirtualAddress)IOMallocLow(newSize);
    if (vaddr == 0)
	return FALSE;

    *allocPtr = vaddr;
    if (newSize != memSize)
	*dataPtr = (vaddr + alignSize - 1) & ~(alignSize - 1);
    else
	*dataPtr = vaddr;
    *sizePtr = newSize;
    *newAttrPtr = IOBuf_Wired | IOBuf_WiredStatic | IOBuf_Contiguous;
    *mapPtr = (IOAddressMap)IOVmTaskSelf();
    return TRUE;
}


+(BOOL)freeMemory:(IOVirtualAddress)addr
       size:(int)memsize
       map:(IOAddressMap)memmap
       attributes:(IOBufferAttributes)attr
{
    if (eisa_present())
	IOFree((void *)addr, memsize);
    else
	IOFreeLow((void *)addr, memsize);
    return TRUE;
}

@end

#endif NOTYET


unix.superglobalmegacorp.com

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