#include #define CPLUSPLUS typedef long unsigned int uint_t; #include "floppy.h" extern "C" { #include //This is for debugging purposes ONLY } caddr_t org_mklinux_swim3_vaddr[2]; caddr_t org_mklinux_swim3_dmvaddr[2]; // Define my superclass #define super IOService // REQUIRED! This macro defines the class's constructors, destructors, // and several other methods I/O Kit requires. Do NOT use super as the // second parameter. You must use the literal name of the superclass. OSDefineMetaClassAndStructors(org_mklinux_iokit_swim3_driver, IOService) static void handleInterrupt(org_mklinux_iokit_swim3_driver *self); static void handleDMAInterrupt(org_mklinux_iokit_swim3_driver *self); // struct bus_device * bool org_mklinux_iokit_swim3_driver::init(OSDictionary *dict) { bool res = super::init(dict); IOLog("SWIM3 Initializing\n"); media_present=false; return res; } void org_mklinux_iokit_swim3_driver::free(void) { IOLog("SWIM3 Freeing\n"); super::free(); } IOService *org_mklinux_iokit_swim3_driver::probe(IOService *provider, SInt32 *score) { IOLog("SWIM3 Probing\n"); if (super::probe(provider, score) == NULL) return NULL; // In all the other cases we do not handle it: return this; } bool org_mklinux_iokit_swim3_driver::start(IOService *provider) { bool res = super::start(provider); struct bus_device *bd; IOMemoryMap * fdMap; IOMemoryMap * DMAfdMap; io_return_t error; IOLog("Starting\n"); if (!res) { IOLog("Failed.\n"); return false; } DAG_Rules=OSDynamicCast(IOBlockStorageDevice, provider); if (!DAG_Rules) { IOLog("Failed.\n"); return false; } bd=this->busdev; if( 0 == (fdMap = provider->mapDeviceMemoryWithIndex( 0 )) ) { IOLog("%s: no fd memory\n", getName()); kprintf("Start is bailing\n"); return false; } this->vaddr = (char *)fdMap->getVirtualAddress(); this->paddr = (char *)fdMap->getPhysicalAddress(); if( 0 == (DMAfdMap = provider->mapDeviceMemoryWithIndex( 1 )) ) { IOLog("%s: no fd memory\n", getName()); kprintf("Start is bailing\n"); return false; } this->dma_vaddr = (char *)DMAfdMap->getVirtualAddress(); this->dma_paddr = (char *)DMAfdMap->getPhysicalAddress(); /* Need to have a unique identifier.... */ bd->unit=(this->paddr == (char *)0xf3015000) ? 0 : 1; org_mklinux_swim3_vaddr[bd->unit] = this->vaddr; org_mklinux_swim3_dmvaddr[bd->unit] = this->vaddr; /* For now, only one device per floppy controller. We're not dealing with 68k.... */ bd->ctlr=0; /* Replace with virtual address of hardware. Note: original code assumed this was physical address. Fake it out with mapping functions that return the original value when asked to map phys->virt. */ bd->address=this->vaddr; /* Now do the equivalent of the open call. */ OSStatus FloppyPluginInit(int unit, BSStorePtr initStore); error = FloppyPluginInit(bd->unit, (BSStorePtr) 0); if (error != D_SUCCESS) { return NULL; } // Now call: // void fdattach(bd); // as soon as fd.c compiles. /* Enable interrupts and install our handler */ provider->registerInterrupt(0, this, (IOInterruptAction) &handleInterrupt, 0); provider->enableInterrupt(0); provider->registerInterrupt(1, this, (IOInterruptAction) &handleDMAInterrupt, 0); provider->enableInterrupt(1); registerService(); return res; return ( createNub ( provider ) ); } IOService * org_mklinux_iokit_swim3_driver::instantiateNub ( void ) { IOLog("org_mklinux_iokit_swim3_driver::instantiateNub entering.\n"); IOService * nub = new org_mklinux_iokit_swim3_device; IOLog("org_mklinux_iokit_swim3_driver::instantiateNub exiting nub = %p.\n", nub); return nub; } bool org_mklinux_iokit_swim3_driver::createNub ( IOService * provider ) { IOService * nub = NULL; IOLog( "org_mklinux_iokit_swim3_driver::createNub entering.\n" ); // Instantiate a generic hard disk nub so a generic driver // can match above us. nub = instantiateNub ( ); if ( nub == NULL ) { IOLog("org_mklinux_iokit_swim3_driver::createNub instantiateNub() failed, returning false\n"); return false; } nub->init ( ); if ( !nub->attach ( this ) ) { // panic since the nub can't attach panic("org_mklinux_iokit_swim3_driver::createNub() unable to attach nub" ); return false; } nub->registerService ( ); // The IORegistry retains the nub, so we can release our refcount // because we don't need it any more. nub->release ( ); IOLog("org_mklinux_iokit_swim3_driver::createNub exiting true.\n"); return true; } void org_mklinux_iokit_swim3_driver::stop(IOService *provider) { IOLog("Stopping\n"); super::stop(provider); /* @@@@ disable the interrupt and unregister! @@@ */ } static void handleInterrupt(org_mklinux_iokit_swim3_driver *self) { /* ssp argument is never used anyway, so pass ourselves.... */ HALISRHandler(self->busdev->unit, self); } static void handleDMAInterrupt(org_mklinux_iokit_swim3_driver *self) { /* ssp argument is never used anyway, so pass ourselves.... */ HALISR_DMA(self->busdev->unit, self); } char * org_mklinux_iokit_swim3_driver::getVendorString ( void ) { return "Apple Computer, Inc.\n"; } char * org_mklinux_iokit_swim3_driver::getProductString ( void ) { return "Internal Floppy Drive\n"; } char * org_mklinux_iokit_swim3_driver::getRevisionString ( void ) { return "??\n"; } char * org_mklinux_iokit_swim3_driver::getAdditionalDeviceInfoString ( void ) { return "Baweep Granaweep Ninibam\n"; } /* Implement the wrappers for: fdopen() fdclose() m765io() fdread() (calls block_io, which calls physio which calls fdstrategy and others) fdwrite() (calls block_io, which calls physio which calls fdstrategy and others) fdgetstat() (get volume size, etc.) fdsetstat() (basically, ioctls) fddevinfo() (get block size) fd_format() ??? (does this even work?) */ //--------------------------------------------------------------------------- // attach to provider. #undef super #define super IOBlockStorageDevice OSDefineMetaClassAndStructors ( org_mklinux_iokit_swim3_device, IOBlockStorageDevice ); bool org_mklinux_iokit_swim3_device::attach ( IOService * provider ) { OSDictionary * dictionary = OSDictionary::withCapacity ( 1 ); if ( !super::attach ( provider ) ) return false; fProvider = OSDynamicCast ( org_mklinux_iokit_swim3_driver, provider ); if ( fProvider == NULL ) { IOLog ( "org_mklinux_iokit_swim3_device: attach; wrong provider type!\n" ); return false; } #if 0 if ( dictionary != NULL ) { dictionary->setObject ( kIOPropertyPhysicalInterconnectTypeKey, fProvider->getProperty ( kIOPropertyPhysicalInterconnectTypeKey ) ); dictionary->setObject ( kIOPropertyPhysicalInterconnectLocationKey, fProvider->getProperty ( kIOPropertyPhysicalInterconnectLocationKey ) ); setProperty ( kIOPropertyProtocolCharacteristicsKey, dictionary ); dictionary->release ( ); } dictionary = OSDictionary::withCapacity ( 1 ); if ( dictionary != NULL ) { char * string; OSString * theString; string = getVendorString ( ); theString = OSString::withCString ( string ); if ( theString != NULL ) { dictionary->setObject ( kIOPropertyVendorNameKey, theString ); theString->release ( ); } string = getProductString ( ); theString = OSString::withCString ( string ); if ( theString != NULL ) { dictionary->setObject ( kIOPropertyProductNameKey, theString ); theString->release ( ); } string = getRevisionString ( ); theString = OSString::withCString ( string ); if ( theString != NULL ) { dictionary->setObject ( kIOPropertyProductRevisionLevelKey, theString ); theString->release ( ); } setProperty ( kIOPropertyDeviceCharacteristicsKey, dictionary ); dictionary->release ( ); } #endif return true; } //--------------------------------------------------------------------------- // detach from provider. void org_mklinux_iokit_swim3_device::detach ( IOService * provider ) { if ( fProvider == provider ) fProvider = 0; super::detach ( provider ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::setProperties ( OSObject * properties ) { OSDictionary * dict = NULL; OSNumber * number = NULL; IOReturn status = kIOReturnSuccess; UInt32 features = 0; IOLog( "org_mklinux_iokit_swim3_device::setProperties called\n"); #if 0 number = ( OSNumber * ) fProvider->getProperty ( kIOATASupportedFeaturesKey ); features = number->unsigned32BitValue ( ); if ( ( features & kIOATAFeatureAdvancedPowerManagement ) == 0 ) { IOLog( "org_mklinux_iokit_swim3_device::setProperties called on unsupported drive\n" ); return kIOReturnUnsupported; } dict = OSDynamicCast ( OSDictionary, properties ); if ( dict != NULL ) { number = OSDynamicCast ( OSNumber, dict->getObject ( "APM Level" ) ); } if ( number != NULL ) { UInt8 apmLevel = number->unsigned8BitValue ( ); if ( ( apmLevel == 0 ) || ( apmLevel == 0xFF ) ) { return kIOReturnBadArgument; } IOLog( "apmLevel = %d\n", apmLevel ); status = fProvider->setAdvancedPowerManagementLevel ( apmLevel, true ); } else status = kIOReturnBadArgument; IOLog( "org_mklinux_iokit_swim3_device::leave setProperties\n" ); return status; #endif return kIOReturnUnsupported; } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::doAsyncReadWrite ( IOMemoryDescriptor * buffer, UInt32 block, UInt32 nblks, IOStorageCompletion completion ) { // Block incoming I/O if we have been terminated if ( isInactive ( ) != false ) { return kIOReturnNotAttached; } // fProvider->checkPowerState ( ); return fProvider->doAsyncReadWrite ( buffer, block, nblks, completion ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::doSyncReadWrite ( IOMemoryDescriptor * buffer, UInt32 block, UInt32 nblks ) { // Block incoming I/O if we have been terminated if ( isInactive ( ) != false ) { return kIOReturnNotAttached; } // fProvider->checkPowerState ( ); return fProvider->doSyncReadWrite ( buffer, block, nblks ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::doEjectMedia ( void ) { return fProvider->doEjectMedia ( ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::doFormatMedia ( UInt64 byteCapacity ) { return fProvider->doFormatMedia ( byteCapacity ); } //--------------------------------------------------------------------------- // UInt32 org_mklinux_iokit_swim3_device::doGetFormatCapacities ( UInt64 * capacities, UInt32 capacitiesMaxCount ) const { return fProvider->doGetFormatCapacities ( capacities, capacitiesMaxCount ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::doLockUnlockMedia ( bool doLock ) { return fProvider->doLockUnlockMedia ( doLock ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::doSynchronizeCache ( void ) { // Block incoming I/O if we have been terminated if ( isInactive ( ) != false ) { return kIOReturnNotAttached; } // fProvider->checkPowerState ( ); return fProvider->doSynchronizeCache ( ); } //--------------------------------------------------------------------------- // char * org_mklinux_iokit_swim3_device::getVendorString ( void ) { return fProvider->getVendorString ( ); } //--------------------------------------------------------------------------- // char * org_mklinux_iokit_swim3_device::getProductString ( void ) { return fProvider->getProductString ( ); } //--------------------------------------------------------------------------- // char * org_mklinux_iokit_swim3_device::getRevisionString ( void ) { return fProvider->getRevisionString ( ); } //--------------------------------------------------------------------------- // char * org_mklinux_iokit_swim3_device::getAdditionalDeviceInfoString ( void ) { return fProvider->getAdditionalDeviceInfoString ( ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::reportBlockSize ( UInt64 * blockSize ) { return fProvider->reportBlockSize ( blockSize ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::reportEjectability ( bool * isEjectable ) { return fProvider->reportEjectability ( isEjectable ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::reportLockability ( bool * isLockable ) { return fProvider->reportLockability ( isLockable ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::reportPollRequirements ( bool * pollIsRequired, bool * pollIsExpensive ) { return fProvider->reportPollRequirements ( pollIsRequired, pollIsExpensive ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::reportMaxReadTransfer ( UInt64 blockSize, UInt64 * max ) { return fProvider->reportMaxReadTransfer ( blockSize, max ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::reportMaxValidBlock ( UInt64 * maxBlock ) { return fProvider->reportMaxValidBlock ( maxBlock ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::reportMaxWriteTransfer ( UInt64 blockSize, UInt64 * max ) { return fProvider->reportMaxWriteTransfer ( blockSize, max ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::reportMediaState ( bool * mediaPresent, bool * changed ) { return fProvider->reportMediaState ( mediaPresent, changed ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::reportRemovability ( bool * isRemovable ) { return fProvider->reportRemovability ( isRemovable ); } //--------------------------------------------------------------------------- // IOReturn org_mklinux_iokit_swim3_device::reportWriteProtection ( bool * isWriteProtected ) { return fProvider->reportWriteProtection ( isWriteProtected ); }