示例#1
0
	virtual void							copyRawContent(uint8_t buffer[]) const {
		// Use ARM instructions that can jump to thumb.
		if (_s_log) fprintf(stderr, "3 ARM instruction shim to jump to %s\n", _target->name());
		OSWriteLittleInt32(&buffer[ 0], 0, 0xe59fc000);	// 	ldr  ip, pc + 4
		OSWriteLittleInt32(&buffer[ 4], 0, 0xe12fff1c);	// 	bx	 ip
		OSWriteLittleInt32(&buffer[ 8], 0, 0);			// 	.long target		
	}
示例#2
0
	virtual void							copyRawContent(uint8_t buffer[]) const {
		// Use ARM instructions that can jump to thumb.
		assert( _target->isThumb() );
		if (_s_log) fprintf(stderr, "4 ARM instruction shim to jump to %s\n", _target->name());
		OSWriteLittleInt32(&buffer[ 0], 0, 0xe59fc004);	// 	ldr  ip, pc + 4
		OSWriteLittleInt32(&buffer[ 4], 0, 0xe08fc00c);	// 	add	 ip, pc, ip
		OSWriteLittleInt32(&buffer[ 8], 0, 0xe12fff1c);	// 	bx	 ip
		OSWriteLittleInt32(&buffer[12], 0, 0);			// 	.long target-this		
	}
示例#3
0
	virtual void							copyRawContent(uint8_t buffer[]) const {
		// Use ARM instructions that can jump to thumb.
		assert( !  _target->isThumb() );
		if (_s_log) fprintf(stderr, "3 Thumb2 instruction shim to jump to %s\n", _target->name());
		OSWriteLittleInt32(&buffer[0], 0, 0xc004f8df);	// 	ldr  ip, pc + 4
		OSWriteLittleInt16(&buffer[4], 0, 0x44fc);		// 	add	 ip, pc, ip
		OSWriteLittleInt16(&buffer[6], 0, 0x4760);		// 	bx	 ip
		OSWriteLittleInt32(&buffer[8], 0, 0x00000000);	// 	.long target-this		
	}
示例#4
0
//	----------------------------------------------------------------------------------------------------
IOReturn	PlatformInterfaceI2S_Mapped::setPeakLevel ( UInt32 channelTarget, UInt32 levelMeterValue ) 
{
	IOReturn		result = kIOReturnSuccess;
	
	switch ( channelTarget ) 
	{
		case kStreamFrontLeft:		OSWriteLittleInt32 ( mI2SBaseAddress, kI2SPeakLevelIn0Offset, levelMeterValue );		break;
		case kStreamFrontRight:		OSWriteLittleInt32 ( mI2SBaseAddress, kI2SPeakLevelIn1Offset, levelMeterValue );		break;
		default:					result = kIOReturnBadArgument;															break;
	}
	return result;
}
示例#5
0
IOReturn AppleI386AGP::commitAGPMemory( IOAGPDevice * master, 
				      IOMemoryDescriptor * memory,
				      IOByteCount agpOffset,
				      IOOptionBits options )
{
    IOPCIAddressSpace 	target = getBridgeSpace();
    IOReturn		err = kIOReturnSuccess;
    UInt32		offset = 0, tmp, agpCtrl;
    IOPhysicalAddress	physAddr;
    IOByteCount		len;
    
//    ok = agpRange->allocate( memory->getLength(), &agpOffset );

    agpCtrl = configRead32(target, kiAGPCTRL);
    agpCtrl &= ~(1 << 7);
    configWrite32( target, kiAGPCTRL, agpCtrl ); 		// b7 gtlb ena

    if(memory)
    {
	assert( agpOffset < systemLength );
	agpOffset /= (page_size / 4);
	while( (physAddr = memory->getPhysicalSegment( offset, &len ))) {
	
	    offset += len;
	    len = (len + 0xfff) & ~0xfff;
	    while( len > 0) {
		OSWriteLittleInt32( gartArray, agpOffset,
					((physAddr & ~0xfff) | 1));
		agpOffset += 4;
		physAddr += page_size;
		len -= page_size;
	    }
	}
	
	// Read back from last entry written to flush entry to main memory.
	tmp = OSReadLittleInt32(gartArray, agpOffset-4);
	
	#if 1
	// Deal with stupid Pentium 4 8-deeps store queue crap.
	for(offset = 0; offset < 64*16; offset += 64)
	{
		tmp = OSReadLittleInt32(gartArray, offset);
		OSWriteLittleInt32(gartArray, offset, tmp);
	}
	#endif
    }
    
    agpCtrl = configRead32(target, kiAGPCTRL);
    agpCtrl |= (1 << 7);
    configWrite32( target, kiAGPCTRL, agpCtrl ); 		// b7 gtlb ena

    return( err );
}
示例#6
0
	virtual void							copyRawContent(uint8_t buffer[]) const {
		OSWriteLittleInt32(&buffer[ 0], 0, 0xe92d400f); // push	{r0, r1, r2, r3, lr}
		OSWriteLittleInt32(&buffer[ 4], 0, 0xebfffffd); // bl	_foo
		OSWriteLittleInt32(&buffer[ 8], 0, 0xe59fc010); // ldr	ip, [pc, #16]
		OSWriteLittleInt32(&buffer[12], 0, 0xe08fc00c); // add	ip, pc, ip
		OSWriteLittleInt32(&buffer[16], 0, 0xe58c0000); // str	r0, [ip]
		OSWriteLittleInt32(&buffer[20], 0, 0xe1a0c000); // mov	ip, r0
		OSWriteLittleInt32(&buffer[24], 0, 0xe8bd400f); // pop	{r0, r1, r2, r3, lr}
		OSWriteLittleInt32(&buffer[28], 0, 0xe12fff1c); // bx	ip
		OSWriteLittleInt32(&buffer[32], 0, 0x00000000); // .long foo$lazyptr - helper + 20
	}
/* write a 32-bit word, little endian */
void appendUint32(
	CFMutableDataRef	buf,
	uint32_t			word)
{
#if 1
	unsigned char cb[4];
	OSWriteLittleInt32(cb, 0, word);
	CFDataAppendBytes(buf, cb, 4);
#else
	/* This is an alternate implementation which may or may not be faster than
	   the above. */
	CFIndex offset = CFDataGetLength(buf);
	UInt8 *bytes = CFDataGetMutableBytePtr(buf);
	CFDataIncreaseLength(buf, 4);
	OSWriteLittleInt32(bytes, offset, word);
#endif
}
示例#8
0
	virtual void							copyRawContent(uint8_t buffer[]) const {
		// push lazy-info-offset
		OSWriteLittleInt32(&buffer[ 0], 0, 0xe52dc004); // str ip, [sp, #-4]!
		// push address of dyld_mageLoaderCache
		OSWriteLittleInt32(&buffer[ 4], 0, 0xe59fc010); // ldr	ip, L1
		OSWriteLittleInt32(&buffer[ 8], 0, 0xe08fc00c); // add	ip, pc, ip
		OSWriteLittleInt32(&buffer[12], 0, 0xe52dc004); // str ip, [sp, #-4]!
		// jump through _fast_lazy_bind
		OSWriteLittleInt32(&buffer[16], 0, 0xe59fc008); // ldr	ip, L2
		OSWriteLittleInt32(&buffer[20], 0, 0xe08fc00c); // add	ip, pc, ip
		OSWriteLittleInt32(&buffer[24], 0, 0xe59cf000); // ldr	pc, [ip]
		OSWriteLittleInt32(&buffer[28], 0, 0x00000000); // L1: .long fFastStubGOTAtom - (helperhelper+16)
		OSWriteLittleInt32(&buffer[32], 0, 0x00000000); // L2: .long _fast_lazy_bind - (helperhelper+28)
	}
/*
 * Update a security buffer's offset to be the current end of data in a CFData.
 */
void secBufOffset(
	CFMutableDataRef	buf,
	CFIndex				offsetIndex)		/* obtained from appendSecBuf() */
{
	CFIndex currPos = CFDataGetLength(buf);
	unsigned char cb[4];
	OSWriteLittleInt32(cb, 0, (uint32_t)currPos);
	CFRange range = {offsetIndex, 4};
	CFDataReplaceBytes(buf, range, cb, 4);
}
示例#10
0
	virtual void							copyRawContent(uint8_t buffer[]) const {
		// Use ARM instructions that can jump to thumb.
		assert( ! _target->isThumb() );
		if (_s_log) fprintf(stderr, "6 Thumb1 instruction shim to jump to %s\n", _target->name());
		OSWriteLittleInt16(&buffer[ 0], 0, 0xb402);		// 	push	{r1}
		OSWriteLittleInt16(&buffer[ 2], 0, 0x4902);		// 	ldr		r1, [pc, #8]
		OSWriteLittleInt16(&buffer[ 4], 0, 0x4479);		// 	add		r1, pc
		OSWriteLittleInt16(&buffer[ 6], 0, 0x468c);		// 	mov		ip, r1
		OSWriteLittleInt16(&buffer[ 8], 0, 0xbc02);		// 	pop		{r1}
		OSWriteLittleInt16(&buffer[10], 0, 0x4760);		// 	bx		ip
		OSWriteLittleInt32(&buffer[12], 0, 0x00000000);	// 	.long target-this		
	}
示例#11
0
bool CLASS::initRxRing( void )
{
    IOPhysicalSegment vector;
    UInt              segCount;    
    IOPhysicalAddress physAddr;
    RxDesc *          descPtr;
    UInt32            cmdStatus;

    // Link the descriptors into a ring.

    for (int i = kRxDescCount - 1 ;i > 0; i--)
    {
        physAddr = fRxDescMemory->getPhysicalSegment(sizeof(RxDesc) * i, 0);
        if (physAddr == 0)
            return false;

        fRxDescBase[i-1].link = physAddr;
    }

    // Wrap the ring - last descriptor points to the first

    fRxDescBase[kRxDescCount - 1].link = fRxDescPhysAddr;

    // Attach cluster mbufs to each receive descriptor.

    for (UInt32 i = 0 ;i < kRxDescCount; i++)
    {
        descPtr = &fRxDescBase[i];

        if (descPtr->packet == 0)
            descPtr->packet = allocatePacket( kRxMaxBufferSize );
        if (descPtr->packet == 0)
            return false;

        segCount = fRxMbufCursor->getPhysicalSegments(
                                  descPtr->packet, &vector, 1);
        if (segCount != 1)
            return false;

        cmdStatus = kDescInterrupt | kDescIncludeCRC |
                    (kRxMaxBufferSize & kDescBufferSizeMask);

        descPtr->bufferPtr = vector.location;
        OSWriteLittleInt32(&descPtr->cmdStatus, 0, cmdStatus);
    }

    fRxHeadIndex = 0;

    return true;
}
/* 
 * Write a security buffer, providing the index into the CFData at which 
 * this security buffer's offset is located. Just before the actual data is written,
 * go back and update the offset with the start of that data using secBufOffset().
 */
void appendSecBuf(
	CFMutableDataRef	buf,
	uint16_t			len,
	CFIndex				*offsetIndex)
{
#if 1
	unsigned char cb[8];
	OSWriteLittleInt16(cb, 0, len);           /* buffer length */
	OSWriteLittleInt16(cb, 2, len);           /* buffer allocated size */
	OSWriteLittleInt32(cb, 4, 0);             /* offset is empty for now */
	CFDataAppendBytes(buf, cb, 8);         
	*offsetIndex = CFDataGetLength(buf) - 4;  /* offset will go here */
#else
	appendUint16(buf, len);					/* buffer length */
	appendUint16(buf, len);					/* buffer allocated size */
	*offsetIndex = CFDataGetLength(buf);	/* offset will go here */
	appendUint32(buf, 0);					/* but it's empty for now */
#endif
}
示例#13
0
static uint64_t WriteMMIO(uint64_t phys, uint8_t length, uint64_t value){
    IOMemoryDescriptor* io_desc;
    IOMemoryMap* io_map;
    uint64_t page_offset = phys & PAGE_MASK;

    log_addr((uint64_t) page_offset, 64, "page_offset");

    xlate_pa_va(phys, &io_desc, &io_map);

    if(io_map) {
        log_addr(io_map->getVirtualAddress(), 64, "io_map->getVirtualAddress");

        switch (length) {
            case 1:
                *(volatile uint8_t *)((uintptr_t)io_map->getVirtualAddress() + page_offset) = value;
                break;
            case 2:
                 OSWriteLittleInt16((void *)io_map->getVirtualAddress(),
                                          page_offset, (uint16_t) value);
                break;
            case 4:
                 OSWriteLittleInt32((void *)io_map->getVirtualAddress(),
                                          page_offset, (uint32_t) value);
                break;
            case 8:
                 OSWriteLittleInt64((void *)io_map->getVirtualAddress(),
                                          page_offset, value);
            default:
                pmem_error("WriteMMIO Incorrect write length");
                break;
        }
    }

    unxlate_pa_va(&io_desc, &io_map);
    return value;
}
示例#14
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void AudioI2SControl::WriteWordLittleEndian(void *address, UInt32 offset, UInt32 value)
{
    OSWriteLittleInt32(address, offset, value);
}
示例#15
0
void CLASS::serviceRxInterrupt(void)
{
    mbuf_t        pkt;
    UInt32        rxStatus;
    UInt32        rxLength;
    UInt32        rxIndex = fRxHeadIndex;
    RxDesc *      descPtr = &fRxDescBase[ rxIndex ];
    bool          pktReplaced;

    rxStatus = OSReadLittleInt32(&descPtr->cmdStatus, 0);

    while (rxStatus & kDescOwn)
    {
        DEBUG_LOG("RX Status = %lx @ index %lu\n", rxStatus, rxIndex);

        // Total packet length, including the 4-byte FCS?

        rxLength = (rxStatus & kDescBufferSizeMask);

        // Packet must be contained within a single descriptor,
        // and must be a good packet.

        if (((rxStatus & (kDescMore | kDescPacketOK)) == kDescPacketOK) &&
            (rxLength <= kIOEthernetMaxPacketSize + 4))
        {
            pkt = replaceOrCopyPacket(
                  &descPtr->packet, rxLength, &pktReplaced);
            if (pkt)
            {
                if (pktReplaced)
                {
                    // New packet added to ring, update descriptor
                    // with new physical address.

                    OSWriteLittleInt32(&descPtr->bufferPtr, 0, 
                                       MBUF_PADDR(descPtr->packet));
                    assert(descPtr->bufferPtr != 0);
                }

                fNetif->inputPacket(
                        pkt, rxLength,
                        IONetworkInterface::kInputOptionQueuePacket );

                NET_STAT(inputPackets, 1);
            }
            else /* !pkt (mbuf shortage) */
            {
                NET_STAT(inputErrors, 1);
                ETH_STAT(dot3RxExtraEntry.resourceErrors, 1);
                DEBUG_LOG("RX RESOURCE ERROR\n");
            }
        }
        else
        {
            recordRxDescriptorErrors(rxStatus);
        }

        // Update the current descriptor and make it owned by NIC.

        rxStatus = kDescInterrupt | kDescIncludeCRC |
                   (kRxMaxBufferSize & kDescBufferSizeMask);

        OSWriteLittleInt32(&descPtr->cmdStatus, 0, rxStatus);

        // Advance to next descriptor.

        rxIndex  = (rxIndex + 1) & (kRxDescCount - 1);
        descPtr  = &fRxDescBase[rxIndex];
        rxStatus = OSReadLittleInt32(&descPtr->cmdStatus, 0);
    }

    fRxHeadIndex = rxIndex;

    // Push up all packets received in the loop above in one shot.

    fNetif->flushInputQueue();
}
示例#16
0
UInt32 CLASS::outputPacket( mbuf_t packet, void * param )
{
    TxDesc *            descNext;
    TxDesc *            descHead;
    TxDesc *            descLast;
    UInt                segCount;
    UInt32              cmdStatus;
    UInt32              tailIndex;
    IOPhysicalSegment   vectors[ kTxMaxSegmentCount ];
    IODebuggerLockState state;

    state = IOKernelDebugger::lock(this);   

    tailIndex = fTxTailIndex;

    // Check if there are enough descriptors to describe the packet
    // buffers. kTxMaxSegmentCount should be large enough to reduce
    // the need to coalesce mbufs.

    if (TX_RING_FREE(fTxHeadIndex, tailIndex) < kTxMaxSegmentCount)
    {
        IOKernelDebugger::unlock(state);
        return kIOReturnOutputStall;
    }

    // Get the next transmit descriptor owned by the driver.

    descHead = &fTxDescBase[tailIndex];
    descNext = descHead;

    // Use the mbuf cursor to generate a list of physical address and
    // length vectors for the network buffers.

    segCount = fTxMbufCursor->getPhysicalSegmentsWithCoalesce(
                              packet, vectors, kTxMaxSegmentCount);
    if (segCount == 0)
    {
        DEBUG_LOG("TX Cursor returned 0 segments\n");
        goto drop_packet;
    }
    assert(segCount <= kTxMaxSegmentCount);

    // Update the first (head) descriptor.
    // Do not set the OWN bit until the rest of the descriptors are done.

    OSWriteLittleInt32(&descHead->bufferPtr, 0, vectors[0].location);
    cmdStatus = (vectors[0].length & kDescBufferSizeMask);
    tailIndex = (tailIndex + 1) & (kTxDescCount - 1);
    descLast  = descHead;
    descNext  = &fTxDescBase[tailIndex];

    for (UInt seg = 1; seg < segCount; seg++)
    {
        // Write cmdStatus for previous descriptor with MORE bit set.

        OSWriteLittleInt32(&descLast->cmdStatus, 0, cmdStatus | kDescMore);

        // Update current descriptor.

        OSWriteLittleInt32(&descNext->bufferPtr, 0, vectors[seg].location);
        cmdStatus = (vectors[seg].length & kDescBufferSizeMask) | kDescOwn;

        tailIndex = (tailIndex + 1) & (kTxDescCount - 1);
        descLast  = descNext;
        descNext  = &fTxDescBase[tailIndex];
    }

    // Last descriptor must have MORE bit cleared.

    if (++fTxInterruptInterval >= (kTxDescCount/kTxMaxSegmentCount/4))
    {
        cmdStatus |= kDescInterrupt;
        fTxInterruptInterval = 0;
    }

    OSWriteLittleInt32(&descLast->cmdStatus, 0, cmdStatus);
    
    // Set OWN bit on head descriptor after all descriptors following it
    // have been prepared.

    descHead->cmdStatus |= OSSwapHostToLittleConstInt32(kDescOwn);

    // Update Head Descriptor.

    descHead->packet    = packet;
    descHead->descLast  = descLast;
    descHead->descCount = segCount;
    descHead->nextIndex = tailIndex;

    // Update free descriptor count after completing the descriptor chain.
    // The order is important otherwise we may race with interrupt handler.

    fTxTailIndex = tailIndex;
    DEBUG_LOG("TX DESC:%d-%ld (size %d)\n",
              descHead-fTxDescBase, fTxTailIndex, mbuf_pkthdr_len(packet));

    // Enable transmitter in case its in txIdle state.

    WriteReg(CR, CR_TXE);

    IOKernelDebugger::unlock(state);
    NET_STAT(outputPackets, 1);
    return kIOReturnOutputSuccess;

drop_packet:
    IOKernelDebugger::unlock(state);
    freePacket(packet);
    ETH_STAT(dot3TxExtraEntry.resourceErrors, 1);
    return kIOReturnOutputDropped;
}
示例#17
0
//	----------------------------------------------------------------------------------------------------
IOReturn	PlatformInterfaceI2S_Mapped::setI2SIOM_PeakLevelIn1 ( UInt32 value ) 
{
	OSWriteLittleInt32(mI2SBaseAddress, kI2SPeakLevelIn1Offset, value);
	return kIOReturnSuccess;
}
示例#18
0
	virtual void							copyRawContent(uint8_t buffer[]) const {
		OSWriteLittleInt32(&buffer[0], 0, 0xe59fc000); // ldr  ip, [pc, #0]
		OSWriteLittleInt32(&buffer[4], 0, 0xea000000); // b	_helperhelper
		OSWriteLittleInt32(&buffer[8], 0, 0);		   // .long lazy-info-offset
	}
示例#19
0
//	----------------------------------------------------------------------------------------------------
IOReturn	PlatformInterfaceI2S_Mapped::setI2SIOM_CodecMsgIn ( UInt32 value ) 
{
	OSWriteLittleInt32(mI2SBaseAddress, kI2SCodecMsgInOffset, value);
	return kIOReturnSuccess;
}
示例#20
0
	virtual void							copyRawContent(uint8_t buffer[]) const {
			OSWriteLittleInt32(&buffer[ 0], 0, 0xE59FF000); // 	ldr	pc, [pc, #foo$lazy_ptr]
	}
示例#21
0
//	----------------------------------------------------------------------------------------------------
IOReturn	PlatformInterfaceI2S_Mapped::setI2SIOMIntControl ( UInt32 intCntrl ) 
{
	OSWriteLittleInt32(mI2SBaseAddress, kI2SIntCtlOffset, intCntrl);
	return kIOReturnSuccess;
}
示例#22
0
	virtual void							copyRawContent(uint8_t buffer[]) const {
			OSWriteLittleInt32(&buffer[ 0], 0, 0xe59fc004);	// 	ldr ip, pc + 12
			OSWriteLittleInt32(&buffer[ 4], 0, 0xe08fc00c);	// 	add ip, pc, ip
			OSWriteLittleInt32(&buffer[ 8], 0, 0xe59cf000);	// 	ldr pc, [ip]
			OSWriteLittleInt32(&buffer[12], 0, 0x00000000);	// 	.long L_foo$lazy_ptr - (L1$scv + 8)
	}
示例#23
0
//	----------------------------------------------------------------------------------------------------
IOReturn	PlatformInterfaceI2S_Mapped::setFrameCount ( UInt32 value ) 
{
	OSWriteLittleInt32 ( mI2SBaseAddress, kI2SFrameCountOffset, value );
	return kIOReturnSuccess;
}
示例#24
0
//	----------------------------------------------------------------------------------------------------
IOReturn	PlatformInterfaceI2S_Mapped::setDataWordSizes ( UInt32 dataWordSizes ) 
{
	debugIOLog ( 3, "± PlatformInterfaceI2S_Mapped::setDataWordSizes ( 0x%0.8X )", dataWordSizes );
	OSWriteLittleInt32(mI2SBaseAddress, kI2SDataWordSizesOffset, dataWordSizes);
	return kIOReturnSuccess;
}
示例#25
0
	virtual void							copyRawContent(uint8_t buffer[]) const {
			OSWriteLittleInt32(&buffer[ 0], 0, 0xe59fc000);	// 	ldr ip, [pc, #0]
			OSWriteLittleInt32(&buffer[ 4], 0, 0xe59cf000);	// 	ldr pc, [ip]
			OSWriteLittleInt32(&buffer[ 8], 0, 0x00000000);	// 	.long   L_foo$lazy_ptr
	}
void writel(unsigned int value, void *addr)
{
	OSWriteLittleInt32((volatile void*)addr, 0, value);
}
示例#27
0
//	----------------------------------------------------------------------------------------------------
IOReturn	PlatformInterfaceI2S_Mapped::setI2SIOM_FrameMatch ( UInt32 value ) 
{
	OSWriteLittleInt32(mI2SBaseAddress, kI2SFrameMatchOffset, value);
	return kIOReturnSuccess;
}
示例#28
0
//	----------------------------------------------------------------------------------------------------
IOReturn	PlatformInterfaceI2S_Mapped::setSerialFormatRegister ( UInt32 serialFormat ) 
{
	debugIOLog ( 3, "± PlatformInterfaceI2S_Mapped::setSerialFormatRegister ( 0x%0.8X )", serialFormat );
	OSWriteLittleInt32 ( mI2SBaseAddress, kI2SSerialFormatOffset, serialFormat );
	return kIOReturnSuccess;
}
示例#29
0
文件: raw.c 项目: B1NG0/cifs
NTSTATUS
SMBRawTransaction(
    SMBHANDLE   inConnection,
    const void *lpInBuffer,
    size_t		nInBufferSize,
    void		*lpOutBuffer,
    size_t		nOutBufferSize,
    size_t		*lpBytesRead)
{
    NTSTATUS            status;
    int                 err;

    void *              hContext;

    struct smb_header   header;
    mbuf_t				words = NULL;
    mbuf_t				bytes = NULL;
    mbuf_t				response = NULL;
	size_t				len;

    const void * ptr;

	bzero(&header, sizeof(header));
    status = SMBServerContext(inConnection, &hContext);
	if (!NT_SUCCESS(status)) {
        return status;
    }

    if ((size_t)nInBufferSize < sizeof(struct smb_header) ||
        (size_t)nOutBufferSize < sizeof(struct smb_header)) {
 		err = STATUS_BUFFER_TOO_SMALL;
        goto errout;
    }

    /* Split the request buffer into the header, the parameter words and the
     * data bytes.
     */
    ptr = lpInBuffer;

    ADVANCE(ptr, sizeof(uint32_t));
    header.command = *(uint8_t *)ptr;

    if ((size_t)nInBufferSize < (sizeof(struct smb_header) + sizeof(uint8_t))) {
 		err = STATUS_BUFFER_TOO_SMALL;
        goto errout;
    }

    ptr = lpInBuffer;
    ADVANCE(ptr, sizeof(struct smb_header));

	len = (*(uint8_t *)ptr) * sizeof(uint16_t);
	ADVANCE(ptr, sizeof(uint8_t));  /* skip word_count field */
	if (mbuf_attachcluster(MBUF_WAITOK, MBUF_TYPE_DATA, &words, (void *)ptr, NULL, len, NULL)) {
		err = STATUS_NO_MEMORY;
        goto errout;
	}
	mbuf_setlen(words, len);
	ADVANCE(ptr, len);      /* skip parameter words */

    if ((uintptr_t)ptr > ((uintptr_t)lpInBuffer + nInBufferSize) ||
        (uintptr_t)ptr < (uintptr_t)mbuf_data(words)) {
		err = STATUS_MARSHALL_OVERFLOW;
        goto errout;
    }

    len = OSReadLittleInt16(ptr, 0);
    ADVANCE(ptr, sizeof(uint16_t)); /* skip byte_count field */
	if (mbuf_attachcluster(MBUF_WAITOK, MBUF_TYPE_DATA, &bytes, (void *)ptr, NULL, len, NULL)) {
		err = STATUS_NO_MEMORY;
        goto errout;
	}
	mbuf_setlen(bytes, len);
    ADVANCE(ptr, len);

    if ((uintptr_t)ptr > ((uintptr_t)lpInBuffer + nInBufferSize) ||
        (uintptr_t)ptr < (uintptr_t)mbuf_data(bytes)) {
		err = STATUS_MARSHALL_OVERFLOW;
        goto errout;
    }

    /* Set up the response buffer so that we leave room to place the
     * SMB header at the front.
     */
    len = (size_t)(nOutBufferSize - sizeof(struct smb_header));
 	if (mbuf_attachcluster(MBUF_WAITOK, MBUF_TYPE_DATA, &response, ((uint8_t *)lpOutBuffer + sizeof(struct smb_header)), NULL, len, NULL)) {
		err = STATUS_NO_MEMORY;
        goto errout;
    }
	
	err = smb_ioc_request(hContext, &header, words, bytes, response);
    if (err) {
		err = STATUS_IO_DEVICE_ERROR;
        goto errout;
    }

    /* Stash the new SMB header at the front of the output buffer so the
     * caller gets the server status code, etc.
     */
    memcpy(lpOutBuffer, lpInBuffer, sizeof(header));
    OSWriteLittleInt32(lpOutBuffer, 0, *(const uint32_t *)(void *)SMB_SIGNATURE);
    OSWriteLittleInt32(lpOutBuffer, offsetof(struct smb_header, status),
                    header.status);
    OSWriteLittleInt16(lpOutBuffer, offsetof(struct smb_header, flags),
					   header.flags);
    OSWriteLittleInt32(lpOutBuffer, offsetof(struct smb_header, flags2),
                    header.flags2);

    *lpBytesRead = mbuf_len(response) + sizeof(struct smb_header);

    /* We return success, even though the server may have failed the call. The
     * caller is responsible for parsing the reply packet and looking at the
     * status field in the header.
     */
    err = STATUS_SUCCESS;
	
errout:
    if (words)
		mbuf_freem(words);
    if (bytes)
		mbuf_freem(bytes);
    if (response)
		mbuf_freem(response);
	return err;
}