Пример #1
0
/*---------------------------------------------------------------------------
 *
 *	connect the device (drive) interrupt to our workloop
 *
 *
 ---------------------------------------------------------------------------*/
bool
AppleKiwiATA::createDeviceInterrupt(void)
{
	// create a device interrupt source and attach it to the work loop
	
	DLOG("AppleKiwiATA createDeviceInterrupt started\n");
	
	_devIntSrc = IOInterruptEventSource::interruptEventSource( 	
					(OSObject *)this,
					(IOInterruptEventSource::Action) &AppleKiwiATA::sDeviceInterruptOccurred, 
					getProvider(), 
					0); 
	
	DLOG("AppleKiwiATA createdDeviceInterruptsource = %x\n", _devIntSrc);
	DLOG("_workLoop = %x\n", _workLoop);
	
	if( !_devIntSrc || getWorkLoop()->addEventSource(_devIntSrc) )
	{
		DLOG("AppleKiwiATA failed create dev intrpt source\n");
		return false;
	}
		
	// enable interrupt to PCI bus
	UInt32 intMaskLE = (busChildNumber == 0)? 0x00000200 : 0x00000400;
	*globalControlReg &= ~intMaskLE; 
	OSSynchronizeIO();

	_devIntSrc->enable();
	
	DLOG("AppleKiwiATA createDeviceInterrupt done\n");
	
	return true;

}
Пример #2
0
void 
AppleKiwiATA::selectIOTiming( ataUnitID unit )
{
	// this chip snoops the SetFeatures command and we don't need to do anything
	// unless it is running with the PLL at 133mhz in the case of the 271. In 
	// that event, we have to override the snoop mode because the chip's internals 
	// don't set the correct mode unless the pll is running at 100 mhz. 

	if(mode6Capable)
	{
		UInt32 bTiming = kPartBTiming33LE;
	
		switch(bitSigToNumeric(busTimings[unit].ataUltraDMASpeedMode) )
		{
			case 2:
				bTiming = kPartBTiming33LE;
			break;
			
			case 4:
				bTiming = kPartBTiming66LE;
			break;
			
			case 5:
				bTiming = kPartBTiming100LE;
			break;
			
			case 6:
				bTiming = kPartBTiming133LE;
			break;
			
			default:
			IOLog("AppleKiwiATA:  error setting timing registers\n");		
			break;
		}
		
		//set the registers
		if( unit == 0)
		{
			*timingAReg0 = kPartATimingLE;
			*timingBReg0  = bTiming;
		} else {
			*timingAReg1 = kPartATimingLE;
			*timingBReg1  = bTiming;		
		}
		
		OSSynchronizeIO();
	}


		return;
}
Пример #3
0
/*---------------------------------------------------------------------------
 *
 ---------------------------------------------------------------------------*/
IOReturn
OHareATA::handleDeviceInterrupt(void)
{

	
	if( _dmaIntExpected != true )
	{
		volatile UInt8 status = *_tfStatusCmdReg;
		OSSynchronizeIO();
		status++; // prevent compiler removal of unused variable.
	}
	return super::handleDeviceInterrupt();
	
}
Пример #4
0
/*---------------------------------------------------------------------------
 *
 *	If there's a timeout, read the drive's status reg to clear any pending
 *	interrupt, then clear the interrupt bit and enable inta# propogation in the
 *	controller.
 *
 ---------------------------------------------------------------------------*/
void
AppleKiwiATA::handleTimeout( void )
{
	if( isBusOnline == false)
	{
		return;
	}

	getLock(true);
	stopDMA();

	volatile UInt8 statusByte = *_tfStatusCmdReg;
	OSSynchronizeIO();

	statusByte++;		// make sure the compiler doesn't drop this.
	
	super::handleTimeout();
	getLock( false);
}
Пример #5
0
IOReturn 
AppleKiwiATA::message (UInt32 type, IOService* provider, void* argument)
{

	switch( type )
	{
		case kATARemovedEvent:
		DLOG( "AppleKiwiATA got remove event.\n");
		// mark the bus as dead.
		if(isBusOnline == true)
		{
			isBusOnline = false;
			// lock the queue, don't dispatch immediates or anything else.
			_queueState = IOATAController::kQueueLocked;
			// disable the interrupt source(s) and timers
			_devIntSrc->disable();
			stopTimer();
			
			_workLoop->removeEventSource(_devIntSrc);
			_workLoop->removeEventSource(_timer);
			
			getLock(true);
			stopDMA();
			
			// disable the controller pins
			*globalControlReg |=  0x00000800;  // LE format
			OSSynchronizeIO();
			
			// flush any commands in the queue
			handleQueueFlush();
			
			// if there's a command active then call through the command gate
			// and clean it up from inside the workloop.
			// 

			if( _currentCommand != 0)
			{
			
				DLOG( "AppleKiwiATA Calling cleanup bus.\n");
				
					_cmdGate->runAction( (IOCommandGate::Action) 
						&AppleKiwiATA::cleanUpAction,
            			0, 			// arg 0
            			0, 		// arg 1
            			0, 0);						// arg2 arg 3

			
			
			}
			_workLoop->removeEventSource(_cmdGate);
			
			getLock(false);
			
			
			DLOG( "AppleKiwiATA notify the clients.\n");			
			terminate( );
			getProvider()->message( 'ofln', 0 );
			
		}
		break;
		
		default:		
		DLOG( "AppleKiwiATA got some other event = %d\n", (int) type);
		return super::message(type, provider, argument);
		break;
	}


	return kATANoErr;

}
Пример #6
0
/*---------------------------------------------------------------------------
 *
 *	Intercept the setup for the control register pointers so we can set the 
 *	timing register in the cell to some safe value prior to scanning for devices 
 *  start.
 *
 *
 ---------------------------------------------------------------------------*/
bool 
AppleKiwiATA::configureTFPointers(void)
{
    DLOG("AppleKiwiATA config TF Pointers \n");

	OSString* locationCompare = OSString::withCString( "1" );
	if( locationCompare->isEqualTo( getProvider()->getLocation() ))
	{ 
		busChildNumber = 1;
	}
	locationCompare->release();
	locationCompare = NULL;

	DLOG("AppleKiwiATA busChildNumber = %d, string = %1s \n", busChildNumber, getProvider()->getLocation());
	


    ioBaseAddrMap[0] = getProvider()->mapDeviceMemoryWithIndex( busChildNumber == 0 ? 0 : 2 );
    if ( ioBaseAddrMap[0] == NULL ) 
    { 
    	return false;
	}	

    volatile UInt8* baseAddress = (volatile UInt8*)ioBaseAddrMap[0]->getVirtualAddress();
	
	_tfDataReg = (volatile UInt16*) (baseAddress + 0x00);

	_tfFeatureReg = baseAddress + 0x01;
	_tfSCountReg = baseAddress + 0x02;
	_tfSectorNReg = baseAddress + 0x03;
	_tfCylLoReg = baseAddress + 0x04;
	_tfCylHiReg = baseAddress + 0x05;
	_tfSDHReg = baseAddress + 0x06;
	_tfStatusCmdReg = baseAddress + 0x07;  

	 DLOG("AppleKiwiATA base address 0 = %lX \n", baseAddress);
	 	 

	// get the address of the alt-status register from the second base address.

    ioBaseAddrMap[1] = getProvider()->mapDeviceMemoryWithIndex( busChildNumber == 0 ? 1 : 3  );
    if ( ioBaseAddrMap[1] == NULL )
    {
    	 return false;
    }
    
    baseAddress = (volatile UInt8 *)ioBaseAddrMap[1]->getVirtualAddress();

 	_tfAltSDevCReg = baseAddress + 2;   

	 DLOG("AppleKiwiATA base address 1 = %lX altStatus at %lx \n", baseAddress, _tfAltSDevCReg);
	 


	// get the address of the BusMaster/DMA control registers from last base address.
    ioBaseAddrMap[2] = getProvider()->mapDeviceMemoryWithIndex( 4 );
    if ( ioBaseAddrMap[2] == NULL )
    {
    	 return false;
    }

    volatile UInt8* bmAddress = (volatile UInt8*)ioBaseAddrMap[2]->getVirtualAddress();
	if( busChildNumber == 1)
	{
		bmAddress += 0x08;  // secondary bus
	}

	 DLOG("AppleKiwiATA base address 2 = %lX \n", bmAddress);

	_bmCommandReg = bmAddress;
	_bmStatusReg = bmAddress + 2;
	_bmPRDAddresReg = (volatile UInt32*) (bmAddress + 4);	

	// get the address of the mmio control registers from base address 5.
    ioBaseAddrMap[3] = getProvider()->mapDeviceMemoryWithIndex( 5 );
    if ( ioBaseAddrMap[3] == NULL )
    {
    	 return false;
    }

    volatile UInt8* bar5Address = (volatile UInt8*)ioBaseAddrMap[3]->getVirtualAddress();
	DLOG("AppleKiwiATA base address 5 = %lx \n", bar5Address);
	
	if( busChildNumber == 1)
	{
		globalControlReg = (volatile UInt32*) (bar5Address + 0x1208);  // secondary bus
		timingAReg0 =(volatile UInt32*) (bar5Address + 0x120c);
		timingBReg0 =(volatile UInt32*) (bar5Address + 0x1210);
		timingAReg1 =(volatile UInt32*) (bar5Address + 0x1214);
		timingBReg1 =(volatile UInt32*) (bar5Address + 0x1218);
		
	} else {
	
		globalControlReg =(volatile UInt32*) (bar5Address + 0x1108);  // primary bus
		timingAReg0 =(volatile UInt32*) (bar5Address + 0x110c);
		timingBReg0 =(volatile UInt32*) (bar5Address + 0x1110);
		timingAReg1 =(volatile UInt32*) (bar5Address + 0x1114);
		timingBReg1 =(volatile UInt32*) (bar5Address + 0x1118);
	}

	// enable the controller pins
	*globalControlReg &= (~ 0x00000800);  // already LE
	OSSynchronizeIO();
	
	busTimings[0].ataUltraDMASpeedMode = 32;
	busTimings[1].ataUltraDMASpeedMode = 32;
	
	DLOG("AppleKiwiATA GCR = %lx \n", *globalControlReg);
	IOSleep(50);
	DLOG("AppleKiwiATA configTFPointers done\n");
	return true;

}
Пример #7
0
/*---------------------------------------------------------------------------
 *
 *	handleDeviceInterrupt - overriden here so we can make sure that the DMA has
 * processed in the event first.
 *
 ---------------------------------------------------------------------------*/
IOReturn
AppleKiwiATA::handleDeviceInterrupt(void)
{	

	if( isBusOnline == false)
	{
		return kIOReturnOffline;
	}

	if( _currentCommand == 0)
	{
	
		return 0;
	}

	UInt32 intMaskLE = (busChildNumber == 0)? 0x00000200 : 0x00000400;
	
	// grab a lock
	getLock(true);
	UInt32 gcrStatus = *globalControlReg;
	UInt8 bmStatus = *_bmStatusReg;
	OSSynchronizeIO();
	
	if( ! (gcrStatus & 0x00000020 )/*bmStatus & 0x04*/ )  // check that the interrupt was asserted since we aren't filtering at interrupt level anymore. 
	{
		getLock( false );
		return 0;
	}
	
	// if this is a DMA command, make sure that the data is fully flushed into system memory
	// before proceeding. The bmStatus register will set the 0x04 flag bit indicating fifo is flushed.
	if( (_currentCommand->getFlags() & mATAFlagUseDMA ) == mATAFlagUseDMA )
	{
		while( !(bmStatus & 0x04) )
		{
			bmStatus = *_bmStatusReg;
			OSSynchronizeIO();
		}
	
	}
	
	// disable interrupt to PCI bus
	*globalControlReg |= intMaskLE; 
	OSSynchronizeIO();

	
	// clear the edge-trigger bit
	*_bmStatusReg = 0x04;
	OSSynchronizeIO();
	
	// super class clears the interrupt request by reading the status reg
	IOReturn result = super::handleDeviceInterrupt();
	

	// enable interrupt to PCI bus
	*globalControlReg &= ~intMaskLE; 
	OSSynchronizeIO();

	getLock( false );
	return result;	
	
}
Пример #8
0
UInt32 AtherosL1Ethernet::outputPacket(mbuf_t m, void *prm)
{
    u32 buf_len;
    at_adapter *adapter=&adapter_;

    u16 next_to_use;
    u16 tpd_req = 1;
    TpdDescr *pTpd ;
    struct at_buffer *buffer_info;

     if(tpd_avail(&adapter->tpd_ring) < tpd_req) {
        // no enough descriptor
        DbgPrint("no enough resource!!\n");
        freePacket(m);
        return kIOReturnOutputDropped;
    }
    

    // init tpd flags
    struct at_tpd_ring* tpd_ring = &adapter->tpd_ring;
    pTpd = AT_TPD_DESC(tpd_ring,
                       ((u16)atomic_read(&tpd_ring->next_to_use)));
    //memset(pTpd, 0, sizeof(TpdDescr));
    memset(((u8*)pTpd + sizeof(pTpd->addr)), 0, (sizeof(TpdDescr) - sizeof(pTpd->addr))); //addr don't clear

    next_to_use = (u16)atomic_read(&tpd_ring->next_to_use);
    buffer_info = tpd_ring->buffer_info+next_to_use; 
    
    if (!buffer_info->memDesc)
    {
        DbgPrint("Tx buffer is null!!\n");
        freePacket(m);
        return kIOReturnOutputDropped;
    }
    
    if (mbuf_pkthdr_len(m) <= AT_TX_BUF_LEN) buf_len = mbuf_pkthdr_len(m);
    else
    {
        DbgPrint("Tx Packet size is too big, droping\n");
        freePacket(m);
        return kIOReturnOutputDropped;
    }
    
    DbgPrint("outputPacket() length %d next_to_use=%d\n", buf_len, next_to_use);
    
    UInt8 *data_ptr = (UInt8 *)buffer_info->memDesc->getBytesNoCopy();
    UInt32 pkt_snd_len = 0;
    mbuf_t cur_buf = m;

    do
    {
        if (mbuf_data(cur_buf)) bcopy(mbuf_data(cur_buf), data_ptr, mbuf_len(cur_buf));
        data_ptr += mbuf_len(cur_buf);
        pkt_snd_len += mbuf_len(cur_buf);
    }
    while(((cur_buf = mbuf_next(cur_buf)) != NULL) && ((pkt_snd_len + mbuf_len(cur_buf)) <= buf_len));
    
    
    buf_len = pkt_snd_len;
    buffer_info->length = (UInt16)buf_len;
    pTpd->buf_len= OSSwapHostToLittleInt16((UInt16)buf_len);
    pTpd->eop = 1;
    
    if(++next_to_use == tpd_ring->count) next_to_use = 0; 
    
    atomic_set(&tpd_ring->next_to_use, next_to_use);
    
    // update mailbox
    at_update_mailbox(adapter);
    
    OSSynchronizeIO();

    freePacket(m);
    return kIOReturnOutputSuccess;
}
Пример #9
0
UInt32 AttansicL2Ethernet::outputPacket(mbuf_t m, void *prm)
{
    at_adapter *adapter=&adapter_;
    tx_pkt_header_t* txph;
    u32 offset, copy_len;
    int txs_unused;
    int txbuf_unused;

    u32 buf_len;

	if (mbuf_pkthdr_len(m) <= MAX_TX_BUF_LEN) buf_len = mbuf_pkthdr_len(m);
	else
	{
		DbgPrint("Tx Packet size is too big, droping\n");
		freePacket(m);
		return kIOReturnOutputDropped;
	}

	txs_unused = TxsFreeUnit(adapter);
	txbuf_unused = TxdFreeBytes(adapter);

	if (txs_unused < 1  || buf_len  > txbuf_unused) {
		// no enough resource
		DbgPrint("no enough resource!!\n");
		freePacket(m);
		return kIOReturnOutputDropped;
	}

	offset = adapter->txd_write_ptr;
DbgPrint("outputPacket() begin, txd_write_ptr %d txs_next_clear %d length %d \n" , adapter->txd_write_ptr,adapter->txs_next_clear,buf_len);

    txph = (tx_pkt_header_t*) 
            (((u8*)adapter->txd_ring)+offset);

	offset += 4;
	if (offset >= adapter->txd_ring_size)
		offset -= adapter->txd_ring_size;

	u32 pkt_snd_len = 0;
	mbuf_t cur_buf = m;

	do
	{
		if (mbuf_data(cur_buf)){
			copy_len = adapter->txd_ring_size - offset;
			if (copy_len >=mbuf_len(cur_buf)) {
				memcpy((u8*)adapter->txd_ring+offset, mbuf_data(cur_buf), mbuf_len(cur_buf));

			} else {
				memcpy((u8*)adapter->txd_ring+offset, mbuf_data(cur_buf), copy_len);
				memcpy((u8*)adapter->txd_ring,  ((u8*)mbuf_data(cur_buf))+copy_len, mbuf_len(cur_buf)-copy_len);
			}
			offset += mbuf_len(cur_buf);
			if (offset >= adapter->txd_ring_size)
				offset -= adapter->txd_ring_size;
			pkt_snd_len += mbuf_len(cur_buf);
		}
	}
	while(((cur_buf = mbuf_next(cur_buf)) != NULL) && ((pkt_snd_len + mbuf_len(cur_buf)) <= buf_len));
	buf_len = pkt_snd_len;
	
	*(u32*)txph = 0;
	txph->pkt_size = buf_len;
	
    offset =  ((offset+3)&~3);
	
	if (offset >= adapter->txd_ring_size)
		offset -= adapter->txd_ring_size;
	adapter->txd_write_ptr = offset;

	// clear txs before send
	adapter->txs_ring[adapter->txs_next_clear].update = 0;
	if (++adapter->txs_next_clear == adapter->txs_ring_size)
		adapter->txs_next_clear = 0;

	AT_WRITE_REGW(  &adapter->hw, 
             REG_MB_TXD_WR_IDX, 
             (adapter->txd_write_ptr>>2));

	OSSynchronizeIO();
	freePacket(m);
	return kIOReturnOutputSuccess;
}