File:  [Apple Darwin 0.x] / drvEIDE / EIDE.drvproj / EIDE.lksproj / DualEide.m
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:40:59 2018 UTC (8 years, 1 month ago) by root
Branches: MAIN, Apple
CVS tags: HEAD, Darwin03
Darwin 0.3 EIDE device driver

/*
 * 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.0 (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 1997-1998 by Apple Computer, Inc., All rights reserved.
 * Copyright 1994-1997 NeXT Software, Inc., All rights reserved.
 *
 * DualEide.m - Dual EIDE controller initialization. 
 *
 * HISTORY
 *
 * 1-Feb-1998	Joe Liu at Apple
 *		Tweaked code to support PIIX which uses the DualEIDE but with a PCI
 *		bus. Not sure if this change will work under 3.3.
 *
 * 18-Aug-1996 	Becky Divinski at NeXT
 *      Created. 
 */

#import <sys/systm.h>

#import <driverkit/KernBus.h>
#import <driverkit/KernDevice.h>
#import <driverkit/KernDeviceDescription.h>
#import <driverkit/IODeviceDescription.h>
#import <driverkit/IODeviceDescriptionPrivate.h>

#import "DualEide.h"
#import "IdeCnt.h"
#import "IdeDisk.h"
#import "AtapiCnt.h"

/* Some mach stuff to create a mach port, kernel/driverkit/driverServerXXX.m */
extern port_t create_dev_port(KernDevice *kernDevice);

#define BUS_TYPE_KEY		"Bus Type"
#define KERN_BUS_FORMAT		"%sKernBus"
#define DEVICE_DESCR_FORMAT	"IO%sDeviceDescription"
#define DEFAULT_BUS			"EISA"	// don't change this! (see comment below)
#define NAME_BUF_LEN		128

__private_extern__ unsigned int	instanceNum = 0;
__private_extern__ BOOL         dualEide = NO;

#if (IO_DRIVERKIT_VERSION >= 400)

static IOEISADeviceDescription *getBusDescription(IOConfigTable *configTable)
{
    id		deviceDescription, ioDeviceDescription = nil;
    id		busClass, defaultBusClass, busDescriptionClass;
    id		defaultBus;
    const char	*busType, *busTypeString;
    char	*nameBuf = NULL;
    id		device;

    defaultBusClass = [KernBus lookupBusClassWithName:DEFAULT_BUS];	
    // XXX
    if (defaultBusClass == nil) {
        sprintf(nameBuf, "Missing %s kernel bus class", DEFAULT_BUS);
        panic(nameBuf);
    }

    defaultBus = [KernBus lookupBusInstanceWithName:DEFAULT_BUS busId:0];

    nameBuf = (char *)IOMalloc(NAME_BUF_LEN);

    busTypeString = [configTable valueForStringKey:BUS_TYPE_KEY];

    if (busTypeString == NULL || *busTypeString == '\0')
        busType = DEFAULT_BUS;
    else
        busType = busTypeString;

    sprintf(nameBuf, KERN_BUS_FORMAT, busType);
    busClass = objc_getClass((const char *)nameBuf);

    if (busClass == nil)	{
        busClass = defaultBusClass;
        busType = DEFAULT_BUS;
    }

	/*
	 * Instead of messaging the 'busClass', we call defaultBusClass
	 * to create a new deviceDescription for us.
	 * This is because PCI for some reason does not allocate resources
	 * for the "I/O Ports" and the "IRQ Levels" key.
	 * The defaultBusClass, which is EISA, does allocate the resources.
	 */
    deviceDescription = [defaultBusClass 
			deviceDescriptionFromConfigTable:configTable];	
    if (deviceDescription == nil) {
        IOLog("getBusDescription: deviceDescriptionFromConfigTable failed");
		return nil;
    }

	/*
	 * Force the bus to be always EISA.
	 */
//	if ([deviceDescription bus] == nil) {
        [deviceDescription setBus:defaultBus];
//    }

    device = [[KernDevice alloc] initWithDeviceDescription:deviceDescription];
    if (device == nil) {
        IOLog("getBusDescription: initWithDeviceDescription failed ");
        return nil;	
    }

    [deviceDescription setDevice: device];
	
    sprintf(nameBuf, "IO%sDeviceDescription", busType);
    busDescriptionClass = objc_getClass((const char *)nameBuf);

    ioDeviceDescription = [[busDescriptionClass alloc]
                                _initWithDelegate: deviceDescription];
    [ioDeviceDescription setDevicePort:create_dev_port(device)];

    return (IOEISADeviceDescription *) ioDeviceDescription;
}

#else /* IO_DRIVERKIT_VERSION < 400 */

id		EISABusClass, theEISABus;

static IOEISADeviceDescription *getBusDescription(IOConfigTable *configTable)
{
    id		deviceDescription, ioDeviceDescription = nil;
    id		busClass, defaultBusClass, busDescriptionClass;
    id		defaultBus;
    id		device;
    char	*nameBuf;
    const char	*busType;
    char	busClassName[128];

    EISABusClass = objc_getClass("EISAKernBus");
    if (EISABusClass == nil)
        panic("Missing EISA kernel bus class");
    theEISABus = [[EISABusClass alloc] init];

    busType = [configTable valueForStringKey:"Bus Type"];

    if (busType) {
        sprintf(busClassName, "%sKernBus", busType);
        busClass = objc_getClass((const char *)busClassName);
    } else {
        busClass = nil;
    }

    if (busClass == nil)
        busClass = objc_getClass("EISAKernBus");

    deviceDescription = [theEISABus
                            deviceDescriptionFromConfigTable:configTable];	

    if (deviceDescription == nil) {
        IOLog("configureDriver: initFromConfigTable failed");
        return nil;
    }

    device = [[KernDevice alloc]
                    initWithDeviceDescription: deviceDescription];

    if (device == nil) {
        IOLog("configureDriver: initFromDeviceDescription failed");
        return nil;		
    }

    [deviceDescription setDevice:device];

    if (busType) {
        sprintf(busClassName, "IO%sDeviceDescription",
                busType);
        busDescriptionClass =
            objc_getClass((const char *)busClassName);
    } else {
        busDescriptionClass = nil;
    }

    if (busDescriptionClass == nil)
        busDescriptionClass =
            objc_getClass("IOEISADeviceDescription");

    ioDeviceDescription = [[busDescriptionClass alloc]
                                _initWithDelegate: deviceDescription];
    [ioDeviceDescription setDevicePort: create_dev_port(device)];

    return (IOEISADeviceDescription *) ioDeviceDescription;
}
#endif IO_DRIVERKIT_VERSION >= 400

@implementation DualEide

+(BOOL)probe:(IODeviceDescription *)devDesc
{
    IOEISADeviceDescription *primaryEISADeviceDescr;
	IOEISADeviceDescription *secondaryEISADeviceDescr;
    IORange		primaryPortRange;
	IORange		secondaryPortRange;
    IORange 	*portRangeList;

    unsigned int	numPortRanges;
    unsigned int	numInterrupts;

    unsigned int primaryInterrupt;
	unsigned int secondaryInterrupt;
    unsigned int *interruptList;
	unsigned int probeFailedCount = 0;

	IOReturn rtn;
    dualEide = YES;
	
    /*
     * Need to create a second device description to send to the second
     * instance.  Start with primary instance's configTable to create another
     * device description.
     */
    primaryEISADeviceDescr   = (IOEISADeviceDescription *) devDesc;
    secondaryEISADeviceDescr = getBusDescription([devDesc configTable]);
    if (secondaryEISADeviceDescr == nil) {
        return NO;
	}

    // Get the interrupts from the primary device description.
    numInterrupts = [primaryEISADeviceDescr numInterrupts];
    interruptList = [primaryEISADeviceDescr interruptList];	

    primaryInterrupt = *interruptList;
	++interruptList;
    secondaryInterrupt = *interruptList;

    // Get the port ranges from the primary device description.
    numPortRanges = [primaryEISADeviceDescr numPortRanges];
    portRangeList = [primaryEISADeviceDescr portRangeList];	

    primaryPortRange.start   = portRangeList->start;
    primaryPortRange.size    = portRangeList->size;
	++portRangeList;
    secondaryPortRange.start = portRangeList->start;
    secondaryPortRange.size  = portRangeList->size;

    // Put the correct interrupt into each device description 	
    [primaryEISADeviceDescr setInterruptList:&primaryInterrupt num:1];
    rtn = [secondaryEISADeviceDescr setInterruptList:&secondaryInterrupt
		num:1];
	if (rtn != IO_R_SUCCESS) {
	    IOLog("%s: Error in setInterruptList (%s)\n", [self name],
			[self stringFromReturn:rtn]);
	}

    // Put the correct port range into each device description
    [primaryEISADeviceDescr setPortRangeList:&primaryPortRange num:1];
    rtn = [secondaryEISADeviceDescr setPortRangeList:&secondaryPortRange
		num:1];
	if (rtn != IO_R_SUCCESS) {
	    IOLog("%s: Error in setPortRangeList (%s)\n", [self name],
			[self stringFromReturn:rtn]);
	}
	
    // Probe the two instances of this Dual EIDE personality.

	instanceNum = 0;	// start with instance 0
	if (![IdeController probe: primaryEISADeviceDescr]) {
#if 0
		IOLog("Instance 0 of Dual EIDE failed the probe.\n");
		dualEide = NO;
		return NO;
#else
		probeFailedCount++;
#endif
	}

	instanceNum++;		// advance to instance 1
	if (![IdeController probe: secondaryEISADeviceDescr]) {
#if 0
		IOLog("Instance 1 of Dual EIDE failed the probe.\n");
		dualEide = NO;
#else
		probeFailedCount++;	
#endif
	}
	
	if (probeFailedCount == 2)
		return NO;
	
    return YES;
}

@end

unix.superglobalmegacorp.com

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