/*
* Insert name in cache if wanted.
* Names with composed chars are not put into the name cache.
+ * Resource forks are not entered in the name cache. This
+ * avoids deadlocks.
*/
if ((cnp->cn_flags & MAKEENTRY)
- && (cnp->cn_namelen == catInfo.nodeData.cnm_length)) {
+ && (cnp->cn_namelen == catInfo.nodeData.cnm_length)
+ && ((H_FORKTYPE(VTOH(target_vp))) != kRsrcFork)) {
/*
* XXX SER - Might be good idea to bcopy(catInfo.nodeData.fsspec.name, cnp->cn_nameptr)
* to "normalize" the name cache. This will avoid polluting the name cache with
return 1;
}
+/*
+ File: DDCPowerOnOffUtils.c <CS3>
+*/
+
+enum{
+ kVCPSendSize = 8,
+ kVCPReplySize = 64,
+ kI2CDisplayWriteAddress = 0x6E,
+ kI2CDisplayReadAddress = 0x6F,
+ // Messed up specification says checksum should be calculated with ACCESS.bus value of 50.
+ kI2CDisplayReadHostCheckSumAddress = 0x50,
+ // Messed up specification says checksum should be calculated with ACCESS.bus value of 50.
+ kI2CDisplayReadHostAddress = 0x51,
+
+ kI2CVCPGetCode = 0x01,
+ kI2CVCPGetLength = 0x82,
+ kI2CVCPGetMessageSize = 0x05,
+
+ kI2CVCPReplyLength = 0x88,
+ kI2CNullReplyLength = 0x80,
+ kI2CNullReplyCheckSum = 0xBE,
+
+ kI2CVCPSetCode = 0x03,
+ kI2CVCPSetLength = 0x84,
+ kI2CVCPReplyCode = 0x02,
+
+ kDDCPowerOn = 0x01,
+ kDDCPowerOff = 0x04
+};
+enum {
+ kBasicI2CCommTransactionsMask = ( (1<<kVideoNoTransactionType) | (1<<kVideoSimpleI2CType)
+ | (1<<kVideoDDCciReplyType) )
+};
+
+void IONDRVFramebuffer::displayI2CPower( bool enable )
+{
+ VDCommunicationRec i2CRecord;
+ VDCommunicationInfoRec i2cInfoRecord;
+ Byte sendBuffer[8];
+ Byte replyBuffer[kVCPReplySize];
+ UInt32 supportedCommFlags = 0;
+ // Don't do it if we're told it's not supported
+ bool setThisDisplay = true;
+
+ //
+ // Some displays (like Fiji) do not support the reading
+ // of the current power state. Others (like Mitsubishi
+ // Diamond Pro 710) report that they do not support
+ // power management calls.
+ //
+ // I'll avoid sending the power command only in the
+ // case that I get a valid reply that does says
+ // it does not support the power selector.
+ //
+
+ bzero( &i2cInfoRecord, sizeof(i2cInfoRecord) );
+ if( noErr != doStatus( cscGetCommunicationInfo, &i2cInfoRecord))
+ return;
+ if( kBasicI2CCommTransactionsMask != (i2cInfoRecord.csSupportedTypes & kBasicI2CCommTransactionsMask))
+ return;
+ if( !shouldDoI2CPower)
+ return;
+
+ supportedCommFlags = i2cInfoRecord.csSupportedCommFlags;
+ bzero( &i2CRecord, sizeof(i2CRecord) );
+ bzero( &sendBuffer, sizeof(sendBuffer) );
+ bzero( &replyBuffer, sizeof(replyBuffer) );
+
+ sendBuffer[0] = kI2CDisplayReadHostAddress;
+ sendBuffer[1] = kI2CVCPGetLength;
+ sendBuffer[2] = kI2CVCPGetCode; // GetVCP command
+ sendBuffer[3] = 0xD6;
+ sendBuffer[4] = kI2CDisplayWriteAddress ^
+ sendBuffer[0] ^ sendBuffer[1] ^
+ sendBuffer[2] ^ sendBuffer[3];
+
+ i2CRecord.csBusID = kVideoDefaultBus;
+ i2CRecord.csSendType = kVideoSimpleI2CType;
+ i2CRecord.csSendAddress = kI2CDisplayWriteAddress;
+ i2CRecord.csSendBuffer = &sendBuffer;
+ i2CRecord.csSendSize = 7;
+ i2CRecord.csReplyType = kVideoDDCciReplyType;
+ i2CRecord.csReplyAddress = kI2CDisplayReadAddress;
+ i2CRecord.csReplyBuffer = &replyBuffer;
+ i2CRecord.csReplySize = kVCPReplySize;
+
+ if( supportedCommFlags & kVideoReplyMicroSecDelayMask )
+ {
+ // We know some displays are slow, this is an important call to get right
+ i2CRecord.csCommFlags |= kVideoReplyMicroSecDelayMask;
+ // 50 milliseconds should be enough time for the display to respond.
+ i2CRecord.csMinReplyDelay = 50 * 1000;
+ }
+
+ if( (noErr == doControl( cscDoCommunication, &i2CRecord))
+ && (kI2CDisplayWriteAddress == replyBuffer[0])
+ && (kI2CVCPReplyLength == replyBuffer[1])
+ && (kI2CVCPReplyCode == replyBuffer[2])) {
+ Byte checkSum = kI2CDisplayReadHostCheckSumAddress ^ // host address
+ replyBuffer[0] ^ // source address
+ replyBuffer[1] ^ // message length (0x88)
+ replyBuffer[2] ^ // VCP type code
+ replyBuffer[3] ^ // result code
+ replyBuffer[4] ^ // VCP op code
+ replyBuffer[5] ^ // VCP type code
+ replyBuffer[6] ^ // Max value MSB
+ replyBuffer[7] ^ // Max value LSB
+ replyBuffer[8] ^ // Current value MSB
+ replyBuffer[9]; // Current value LSB
+
+ if( (checkSum == replyBuffer[10]) && // Did the check sum match AND
+ (0 != replyBuffer[3])) // Are we not supposed to support this feature?
+ setThisDisplay = false; // Don't do it if we're told it's not supported
+ }
+
+ if( setThisDisplay) {
+
+ bzero( &i2CRecord, sizeof(i2CRecord) );
+ bzero( &sendBuffer, sizeof(sendBuffer) );
+ bzero( &replyBuffer, sizeof(replyBuffer) );
+
+ sendBuffer[0] = kI2CDisplayReadHostAddress;
+ sendBuffer[1] = kI2CVCPSetLength;
+ sendBuffer[2] = kI2CVCPSetCode; // SetVCP command
+ sendBuffer[3] = 0xD6;
+ sendBuffer[4] = 0; // MSB
+ sendBuffer[5] = enable ? kDDCPowerOn : kDDCPowerOff; // LSB
+ sendBuffer[6] = kI2CDisplayWriteAddress ^
+ sendBuffer[0] ^ sendBuffer[1] ^
+ sendBuffer[2] ^ sendBuffer[3] ^
+ sendBuffer[4] ^ sendBuffer[5];
+
+ i2CRecord.csBusID = kVideoDefaultBus;
+ i2CRecord.csSendAddress = kI2CDisplayWriteAddress;
+ i2CRecord.csSendType = kVideoSimpleI2CType;
+ i2CRecord.csSendBuffer = &sendBuffer;
+ i2CRecord.csSendSize = 7;
+ i2CRecord.csReplyType = kVideoNoTransactionType;
+ i2CRecord.csReplyAddress = 0;
+ i2CRecord.csReplyBuffer = 0;
+ i2CRecord.csReplySize = 0;
+
+ if( supportedCommFlags & kVideoReplyMicroSecDelayMask) {
+ // We know some displays are slow, this is an important call to get right
+ i2CRecord.csCommFlags |= kVideoReplyMicroSecDelayMask;
+ // 50 milliseconds should be enough time for the display to respond.
+ i2CRecord.csMinReplyDelay = 50 * 1000;
+ }
+
+ doControl( cscDoCommunication, &i2CRecord);
+ }
+}
IOReturn IONDRVFramebuffer::setAttributeForConnection( IOIndex connectIndex,
IOSelect attribute, UInt32 info )
{
VDSyncInfoRec theVDSyncInfoRec;
VDPowerStateRec sleepInfo;
-
switch( attribute ) {
case kConnectionSyncEnable:
sleepInfo.powerReserved2 = 0;
doControl( cscSetPowerState, &sleepInfo);
+ displayI2CPower( ((info>>8) & 0xff) ? false : true );
+
err = kIOReturnSuccess;
break;
== kNeedFlags );
}
+// I2C first year for Apple displays.
+// Apple monitors older than this (and Manta)
+// are never called with I2C commands
+enum {
+ kFirstAppleI2CYear = 1999,
+ kAppleVESAVendorID = 0x0610
+};
+
+struct EDID {
+ UInt8 header[8];
+ UInt8 vendorProduct[4];
+ UInt8 serialNumber[4];
+ UInt8 weekOfManufacture;
+ UInt8 yearOfManufacture;
+ UInt8 version;
+ UInt8 revision;
+ UInt8 displayParams[5];
+ UInt8 colorCharacteristics[10];
+ UInt8 establishedTimings[3];
+ UInt16 standardTimings[8];
+ UInt8 descriptors[4][18];
+ UInt8 extension;
+ UInt8 checksum;
+};
+
+static bool IsApplePowerBlock(UInt8 * theBlock)
+{
+ return( theBlock &&
+ 0x00000000 == *(UInt32 *)&theBlock[0] &&
+ 0x00 == theBlock[4] &&
+ 0x06 == theBlock[5] &&
+ 0x10 == theBlock[6] );
+}
+
IOReturn IONDRVFramebuffer::getDDCBlock( IOIndex /* connectIndex */,
UInt32 blockNumber,
IOSelect blockType,
actualLength = kDDCBlockSize;
bcopy( ddcRec.ddcBlockData, data, actualLength);
*length = actualLength;
+
+ if( (1 == blockNumber) && (kIODDCBlockTypeEDID == blockType)
+ && (actualLength >= sizeof( EDID))) do {
+
+ EDID * edid;
+ UInt32 vendor;
+ UInt32 product;
+
+ edid = (EDID *) data;
+ vendor = (edid->vendorProduct[0] << 8) | edid->vendorProduct[1];
+ product = (edid->vendorProduct[3] << 8) | edid->vendorProduct[2];
+ if( kAppleVESAVendorID == vendor) {
+ if( (0x01F4 == product) || (0x9D02 == product))
+ continue;
+ if( edid->yearOfManufacture && ((edid->yearOfManufacture + 1990) < kFirstAppleI2CYear))
+ continue;
+ }
+ shouldDoI2CPower = (IsApplePowerBlock( &edid->descriptors[1][0])
+ || IsApplePowerBlock( &edid->descriptors[2][0])
+ || IsApplePowerBlock( &edid->descriptors[3][0]));
+
+ } while( false );
}
+
+ IOLog("%s: i2cPower %d\n", getName(), shouldDoI2CPower);
+
return( err);
}
req->setCDB( &scsiCDB );
req->setPointers(cx->senseDataDesc, 255, false, true);
+ buffer->retain(); /* bump the retain count */
cx->memory = buffer;
req->setPointers( cx->memory, cx->memory->getLength(), false );
kVideoDDCciReplyType = 2 /* DDC/ci message (with imbedded length)*/
};
-
+// VDCommunicationRec.csCommFlags and VDCommunicationInfoRec.csSupportedCommFlags
+enum {
+ kVideoReplyMicroSecDelayMask = (1<<0) /* If set, the driver should delay csMinReplyDelay micro seconds between send and receive*/
+};
struct VDResolutionInfoRec {
struct VDCommunicationRec {
SInt32 csBusID; /* kVideoDefaultBus for single headed cards.*/
- UInt32 csReserved0; /* Always zero*/
- UInt32 csReserved1; /* Always zero*/
+ UInt32 csCommFlags; /* Always zero*/
+ UInt32 csMinReplyDelay; /* Minimum delay between send and reply transactions (units depend on csCommFlags)*/
UInt32 csReserved2; /* Always zero*/
UInt32 csSendAddress; /* Usually I2C address (eg 0x6E)*/
SInt32 csMaxBus; /* Max bus (usually kVideoDefaultBus). Used to probe additional busses*/
UInt32 csSupportedTypes; /* Bit field for first 32 supported transaction types. Eg. 0x07 => support for kVideoNoTransactionType, kVideoSimpleI2CType and kVideoDDCciReplyType.*/
- UInt32 csReserved1; /* Always zero*/
+ UInt32 csSupportedCommFlags; /* Return the flags csCommFlags understood by this driver. */
UInt32 csReserved2; /* Always zero*/
UInt32 csReserved3; /* Always zero*/
struct _VSLService * vslServices;
UInt32 accessFlags;
+ UInt8 shouldDoI2CPower;
- UInt32 __reserved[32];
+ UInt8 __reservedB[3];
+ UInt32 __reservedA[31];
private:
OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 0);
virtual void getCurrentConfiguration( void );
static const IOTVector * _undefinedSymbolHandler( void * self,
const char * libraryName, const char * symbolName );
+ void displayI2CPower( bool enable );
public:
virtual IOReturn doControl( UInt32 code, void * params );
.L_invalidate_dcache_invalidate_loop:
subic r4, r4, CACHE_LINE_SIZE
dcbi r3, r4
- dcbi r3, r4
bdnz .L_invalidate_dcache_invalidate_loop
.L_invalidate_dcache_done:
.L_invalidate_dcache_one_line:
xor r4,r4,r4
dcbi 0,r3
- dcbi 0,r3
b .L_invalidate_dcache_done
/*
.L_invalidate_icache_invalidate_loop:
subic r4, r4, CACHE_LINE_SIZE
icbi r3, r4
- icbi r3, r4
bdnz .L_invalidate_icache_invalidate_loop
.L_invalidate_icache_done:
- /* Sync restore msr if it was modified */
- cmpwi r5, 0
sync /* make sure invalidates have completed */
- beq+ 0f
mtmsr r6 /* Restore original translations */
isync /* Ensure data translations are on */
-0:
blr
.L_invalidate_icache_one_line:
xor r4,r4,r4
icbi 0,r3
- icbi 0,r3
b .L_invalidate_icache_done
eieio /* Make sure that the tlbie happens first */
tlbsync /* wait for everyone to catch up */
+ isync
its603a: sync /* Make sure of it all */
stw r11,0(r12) /* Clear the tlbie lock */
eieio /* Make sure that the tlbie happens first */
tlbsync /* wait for everyone to catch up */
+ isync
its603p: stw r11,0(r12) /* Clear the lock */
srw r5,r5,r8 /* Make a "free slot" mask */
eieio /* Make sure that the tlbie happens first */
tlbsync /* wait for everyone to catch up */
+ isync
its603pv: stw r11,0(r12) /* Clear the lock */
srw r5,r5,r8 /* Make a "free slot" mask */
eieio /* Make sure that the tlbie happens first */
tlbsync /* wait for everyone to catch up */
+ isync
its603av: stw r11,0(r12) /* Clear the lock */
srw r5,r5,r8 /* Make a "free slot" mask */
eieio /* Make sure that the tlbie happens first */
tlbsync /* wait for everyone to catch up */
+ isync
its603co: stw r11,0(r12) /* Clear the lock */
srw r5,r5,r8 /* Make a "free slot" mask */
eieio ; Make sure that the tlbie happens first
tlbsync ; wait for everyone to catch up
+ isync
htr603: stw r11,0(r12) ; Clear the lock
srw r5,r5,r8 ; Make a "free slot" mask
eieio /* Make sure that the tlbie happens first */
tlbsync /* wait for everyone to catch up */
+ isync
its603: rlwinm. r21,r21,0,0,0 ; See if we just stole an autogenned entry
sync /* Make sure of it all */
blt rbHash ; Nope, length is right
subi r6,r4,32+31 ; Back down to correct length
-rbHash: xor r2,r8,r5 ; Hash into table
+rbHash: rlwinm r5,r5,0,10,25 ; Keep only the page index
+ xor r2,r8,r5 ; Hash into table
and r2,r2,r4 ; Wrap into the table
add r2,r2,r12 ; Point right at the PCA
eieio ; Make sure that the tlbie happens first
tlbsync ; wait for everyone to catch up
+ isync
rbits603a: sync ; Wait for quiet again
stw r2,0(r12) ; Unlock invalidates
tlbsync ; Sync all TLBs
sync
+ isync
cinoSMP: stw r2,0(r5) ; Unlock TLBIE lock
ENTRY(save_queue,TAG_NO_FRAME_USED)
- mfmsr r12 /* Get the MSR */
- lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */
- andi. r11,r12,0x7FCF /* Turn off all translation and 'rupts */
- ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */
- mtmsr r11 /* Make the MSR current */
-
- isync
+ mfsprg r9,2 ; Get the feature flags
+ mr r11,r3 ; Save the block
+ mtcrf 0x04,r9 ; Set the features
+ mfmsr r12 ; Get the MSR
+ lis r10,HIGH_ADDR(EXT(saveanchor)) ; Get the high part of the anchor
+ andi. r3,r12,0x7FCF ; Turn off all translation and rupts
+ ori r10,r10,LOW_ADDR(EXT(saveanchor)) ; Bottom half of the anchor
+
+ bt pfNoMSRirb,sqNoMSR ; No MSR...
+
+ mtmsr r3 ; Translation and all off
+ isync ; Toss prefetch
+ b sqNoMSRx
+
+sqNoMSR: li r0,loadMSR ; Get the MSR setter SC
+ sc ; Set it
+sqNoMSRx:
#if 0
- rlwinm. r3,r3,0,0,19 /* (TEST/DEBUG) */
+ rlwinm. r3,r11,0,0,19 /* (TEST/DEBUG) */
bne+ notraceit /* (TEST/DEBUG) */
BREAKPOINT_TRAP /* (TEST/DEBUG) */
notraceit: /* (TEST/DEBUG) */
#else
- rlwinm r3,r3,0,0,19 /* Make sure it's clean and tidy */
+ rlwinm r3,r11,0,0,19 /* Make sure it's clean and tidy */
#endif
- lwarx r9,0,r10 ; ?
-
sqlck: lwarx r9,0,r10 /* Grab the lock value */
li r8,1 /* Use part of the delay time */
mr. r9,r9 /* Is it locked? */
ENTRY(save_dequeue,TAG_NO_FRAME_USED)
+ mfsprg r9,2 ; Get the feature flags
mfmsr r12 /* Get the MSR */
+ mtcrf 0x04,r9 ; Set the features
lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */
- andi. r11,r12,0x7FCF /* Turn off all translation and 'rupts */
+ andi. r3,r12,0x7FCF /* Turn off all translation and 'rupts */
ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */
- mtmsr r11 /* Make the MSR current */
- isync /* Make sure translation is off */
- lwarx r9,0,r10 ; ?
+ bt pfNoMSRirb,sdNoMSR ; No MSR...
+
+ mtmsr r3 ; Translation and all off
+ isync ; Toss prefetch
+ b sdNoMSRx
+
+sdNoMSR: li r0,loadMSR ; Get the MSR setter SC
+ sc ; Set it
+sdNoMSRx:
sdqlck: lwarx r9,0,r10 /* Grab the lock value */
li r8,1 /* Use part of the delay time */
cmplwi cr1,r1,0 ; Set CR1_ne to indicate we want virtual address
-csaveget: mfmsr r11 /* Get the MSR */
+csaveget: mfsprg r9,2 ; Get the feature flags
+ mfmsr r11 ; Get the MSR
+ mtcrf 0x04,r9 ; Set the features
lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */
- andi. r8,r11,0x7FCF /* Turn off all translation and 'rupts */
+ andi. r3,r11,0x7FCF /* Turn off all translation and 'rupts */
ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */
- mtmsr r8 /* Make the MSR current */
- isync ; Make sure it is done
+
+ bt pfNoMSRirb,sgNoMSR ; No MSR...
+
+ mtmsr r3 ; Translation and all off
+ isync ; Toss prefetch
+ b sgNoMSRx
- lwarx r9,0,r10 ; ?
+sgNoMSR: mr r9,r0 ; Save this
+ li r0,loadMSR ; Get the MSR setter SC
+ sc ; Set it
+ mr r0,r9 ; Restore it
+
+sgNoMSRx:
sglck: lwarx r9,0,r10 /* Grab the lock value */
li r7,1 /* Use part of the delay time */
nodoublefret: /* (TEST/DEBUG) */
#endif
+ mfsprg r9,2 ; Get the feature flags
lwz r7,SAVflags(r3) /* Get the flags */
rlwinm r6,r3,0,0,19 /* Round back down to the savearea page block */
andis. r7,r7,HIGH_ADDR(SAVinuse) /* Still in use? */
mfmsr r12 /* Get the MSR */
bnelr- /* Still in use, just leave... */
lwz r5,SACvrswap(r6) /* Get the conversion to real */
+ mr r8,r3 ; Save the savearea address
+ mtcrf 0x04,r9 ; Set the features
lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */
- andi. r11,r12,0x7FCF /* Turn off all translation and 'rupts */
+ andi. r3,r12,0x7FCF /* Turn off all translation and 'rupts */
ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */
- mtmsr r11 /* Make the MSR current */
- isync /* Make sure translation is off */
+
+ bt pfNoMSRirb,srNoMSR ; No MSR...
+
+ mtmsr r3 ; Translation and all off
+ isync ; Toss prefetch
+ b srNoMSRx
+
+srNoMSR: li r0,loadMSR ; Get the MSR setter SC
+ sc ; Set it
+srNoMSRx:
mfsprg r11,1 /* Get the active save area */
- xor r3,r3,r5 /* Get the real address of the savearea */
+ xor r3,r8,r5 /* Get the real address of the savearea */
cmplw r11,r3 /* Are we trying to toss the active one? */
xor r6,r6,r5 /* Make the savearea block real also */
beq- srbigtimepanic /* This is a no-no... */
lis r8,0x8000 /* Build a bit mask and assume first savearea */
srw r8,r8,r7 /* Get bit position of do deallocate */
- lwarx r11,0,r10 ; ?
-
srlck: lwarx r11,0,r10 /* Grab the lock value */
li r7,1 /* Use part of the delay time */
mr. r11,r11 /* Is it locked? */
* block and disable for interruptions.
* Note really well: this is only for debugging, don't expect it to always work!
*
- * We take a virtual address in R4 to save the original MSR, and
+ * We take a virtual address in R3 to save the original MSR, and
* return the virtual address.
*
*/
ENTRY(save_deb,TAG_NO_FRAME_USED)
+ mfsprg r9,2 ; Get the feature flags
mfmsr r12 /* Get the MSR */
lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */
+ mtcrf 0x04,r9 ; Set the features
stw r12,0(r3) /* Save it */
- andi. r11,r12,0x7FCF /* Turn off all translation and 'rupts */
+ andi. r3,r12,0x7FCF /* Turn off all translation and 'rupts */
ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */
- mtmsr r11 /* Make the MSR current */
- isync /* Make sure translation is off */
+
+ bt pfNoMSRirb,sdbNoMSR ; No MSR...
+
+ mtmsr r3 ; Translation and all off
+ isync ; Toss prefetch
+ b sdbNoMSRx
+
+sdbNoMSR: li r0,loadMSR ; Get the MSR setter SC
+ sc ; Set it
+sdbNoMSRx:
+
lwz r3,SVfree(r10) /* Get the physical first in list */
andi. r11,r12,0x7FFF /* Clear only interruption */
lwz r5,SACvrswap(r3) /* Get the conversion to virtual */
m = (vm_page_t)zget(vm_page_zone);
if (m) {
m->free = FALSE;
-#if MACH_ASSERT || ZONE_DEBUG
vm_page_init(m, vm_page_fictitious_addr);
m->fictitious = TRUE;
-#endif /* MACH_ASSERT || ZONE_DEBUG */
}
c_vm_page_grab_fictitious++;
{
vm_map_entry_t entry;
int caller_flags;
+ int sync_cow_data = FALSE;
+ vm_object_t local_object;
+ vm_offset_t local_offset;
+ vm_offset_t local_start;
+ kern_return_t ret;
caller_flags = *flags;
+ if (!(caller_flags & UPL_COPYOUT_FROM)) {
+ sync_cow_data = TRUE;
+ }
if(upl == NULL)
return KERN_INVALID_ARGUMENT;
REDISCOVER_ENTRY:
}
}
if (entry->is_sub_map) {
+ vm_map_t submap;
+
+ submap = entry->object.sub_map;
+ local_start = entry->vme_start;
+ local_offset = entry->offset;
+ vm_map_reference(submap);
vm_map_unlock(map);
- return (vm_map_get_upl(entry->object.sub_map,
- entry->offset + (offset - entry->vme_start),
+
+ ret = (vm_map_get_upl(submap,
+ local_offset + (offset - local_start),
upl_size, upl, page_list, count,
flags, force_data_sync));
+
+ vm_map_deallocate(submap);
+ return ret;
}
- if (!(caller_flags & UPL_COPYOUT_FROM)) {
+ if (sync_cow_data) {
if (entry->object.vm_object->shadow) {
- int flags;
+ int flags;
+
+ local_object = entry->object.vm_object;
+ local_start = entry->vme_start;
+ local_offset = entry->offset;
+ vm_object_reference(local_object);
vm_map_unlock(map);
- vm_object_reference(entry->object.vm_object);
- if(entry->object.vm_object->copy == NULL) {
+ if(local_object->copy == NULL) {
flags = MEMORY_OBJECT_DATA_SYNC;
} else {
flags = MEMORY_OBJECT_COPY_SYNC;
}
+
+ if((local_object->paging_offset) &&
+ (local_object->pager == 0)) {
+ /*
+ * do a little clean-up for our unorthodox
+ * entry into a pager call from a non-pager
+ * context. Normally the pager code
+ * assumes that an object it has been called
+ * with has a backing pager and so does
+ * not bother to check the pager field
+ * before relying on the paging_offset
+ */
+ vm_object_lock(local_object);
+ if (local_object->pager == 0) {
+ local_object->paging_offset = 0;
+ }
+ vm_object_unlock(local_object);
+ }
memory_object_lock_request(
- entry->object.vm_object,
- (offset - entry->vme_start)
- + entry->offset,
+ local_object, ((offset - local_start)
+ + local_offset) +
+ local_object->paging_offset,
(vm_object_size_t)*upl_size, FALSE,
flags,
VM_PROT_NO_CHANGE, NULL, 0);
- vm_map_lock(map);
+ sync_cow_data = FALSE;
+ goto REDISCOVER_ENTRY;
}
}
if (force_data_sync) {
+
+ local_object = entry->object.vm_object;
+ local_start = entry->vme_start;
+ local_offset = entry->offset;
+ vm_object_reference(local_object);
vm_map_unlock(map);
- vm_object_reference(entry->object.vm_object);
+ if((local_object->paging_offset) &&
+ (local_object->pager == 0)) {
+ /*
+ * do a little clean-up for our unorthodox
+ * entry into a pager call from a non-pager
+ * context. Normally the pager code
+ * assumes that an object it has been called
+ * with has a backing pager and so does
+ * not bother to check the pager field
+ * before relying on the paging_offset
+ */
+ vm_object_lock(local_object);
+ if (local_object->pager == 0) {
+ local_object->paging_offset = 0;
+ }
+ vm_object_unlock(local_object);
+ }
+
memory_object_lock_request(
- entry->object.vm_object,
- (offset - entry->vme_start)
- + entry->offset,
- (vm_object_size_t)*upl_size, FALSE,
- MEMORY_OBJECT_DATA_SYNC,
- VM_PROT_NO_CHANGE,
- NULL, 0);
- vm_map_lock(map);
+ local_object, ((offset - local_start)
+ + local_offset) +
+ local_object->paging_offset,
+ (vm_object_size_t)*upl_size, FALSE,
+ MEMORY_OBJECT_DATA_SYNC,
+ VM_PROT_NO_CHANGE,
+ NULL, 0);
+ force_data_sync = FALSE;
+ goto REDISCOVER_ENTRY;
}
if(!(entry->object.vm_object->private)) {
} else {
*flags = UPL_DEV_MEMORY | UPL_PHYS_CONTIG;
}
+ local_object = entry->object.vm_object;
+ local_offset = entry->offset;
+ local_start = entry->vme_start;
+ vm_object_reference(local_object);
vm_map_unlock(map);
- return(vm_fault_list_request(entry->object.vm_object,
- ((offset - entry->vme_start) + entry->offset),
+ ret = (vm_fault_list_request(local_object,
+ ((offset - local_start) + local_offset),
*upl_size,
upl,
page_list,
*count,
caller_flags));
+ vm_object_deallocate(local_object);
+ return(ret);
}
vm_map_unlock(map);
sm_info.alternate_base = shared_region->alternate_base;
sm_info.alternate_next = shared_region->alternate_next;
sm_info.flags = shared_region->flags;
- sm_info.self = shared_region;
+ sm_info.self = (vm_offset_t)shared_region;
lsf_remove_regions_mappings(shared_region, &sm_info);
pmap_remove(((vm_named_entry_t)