1/* 2 * Copyright (c) 1998-2008 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22/* IOMbufMemoryCursor.cpp created by gvdl on 1999-1-20 */ 23 24#include <sys/cdefs.h> 25 26__BEGIN_DECLS 27#include <IOKit/assert.h> 28 29#include <sys/param.h> 30#include <sys/mbuf.h> 31struct mbuf * m_getpackets(int num_needed, int num_with_pkthdrs, int how); 32__END_DECLS 33 34#include <IOKit/network/IOMbufMemoryCursor.h> 35#include <IOKit/IOLib.h> 36 37#ifndef MIN 38#define MIN(a,b) (((a)<(b))?(a):(b)) 39#endif /* MIN */ 40 41#define next_page(x) trunc_page(x + PAGE_SIZE) 42 43#if 0 44#define ERROR_LOG(args...) IOLog(args) 45#else 46#define ERROR_LOG(args...) 47#endif 48 49/* Define the meta class stuff for the entire file here */ 50OSDefineMetaClassAndStructors(IOMbufMemoryCursor, IOMemoryCursor) 51OSMetaClassDefineReservedUnused( IOMbufMemoryCursor, 0); 52OSMetaClassDefineReservedUnused( IOMbufMemoryCursor, 1); 53OSMetaClassDefineReservedUnused( IOMbufMemoryCursor, 2); 54OSMetaClassDefineReservedUnused( IOMbufMemoryCursor, 3); 55 56OSDefineMetaClassAndStructors(IOMbufNaturalMemoryCursor, IOMbufMemoryCursor) 57OSDefineMetaClassAndStructors(IOMbufBigMemoryCursor, IOMbufMemoryCursor) 58OSDefineMetaClassAndStructors(IOMbufLittleMemoryCursor, IOMbufMemoryCursor) 59 60#ifdef __ppc__ 61OSDefineMetaClassAndStructors(IOMbufDBDMAMemoryCursor, IOMbufMemoryCursor) 62#endif /* __ppc__ */ 63 64/*********************** class IOMbufMemoryCursor ***********************/ 65#define super IOMemoryCursor 66 67bool IOMbufMemoryCursor::initWithSpecification(OutputSegmentFunc outSeg, 68 UInt32 maxSegmentSize, 69 UInt32 maxTransferSize, 70 UInt32 align) 71{ 72 return false; 73} 74 75bool IOMbufMemoryCursor::initWithSpecification(OutputSegmentFunc inOutSeg, 76 UInt32 inMaxSegmentSize, 77 UInt32 inMaxNumSegments) 78{ 79 if (!super::initWithSpecification(inOutSeg, inMaxSegmentSize, 0, 1)) 80 return false; 81 82#if 0 83 // It is too confusing to force the max segment size to be at least 84 // as large as a page. Most Enet devices only have 11-12 bit fields, 85 // enough for a full size frame, and also the PAGE_SIZE parameter 86 // may be architecture dependent. 87 88 assert(inMaxSegmentSize >= PAGE_SIZE); 89 if (inMaxSegmentSize < PAGE_SIZE) 90 return false; 91#else 92 if (!inMaxSegmentSize) 93 return false; 94#endif 95 96 maxSegmentSize = MIN(maxSegmentSize, PAGE_SIZE); 97 maxNumSegments = inMaxNumSegments; 98 coalesceCount = 0; 99 100 return true; 101} 102 103// 104// Copy the src packet into the destination packet. The amount to copy is 105// determined by the dstm->m_len, which is setup by analyseSegments, see below. 106// Mbufs(except for the head) from the source are freed as they are copied and the 107// remaining uncopied mbufs are attached to the end of the dest chain. 108#define BCOPY(s, d, l) do { bcopy((void *) s, (void *) d, l); } while(0) 109 110static inline void coalesceSegments(mbuf_t srcm, mbuf_t dstm) 111{ 112 uintptr_t src, dst; 113 SInt32 srcLen, dstLen; 114 mbuf_t temp; 115 mbuf_t head = srcm; 116 117 srcLen = mbuf_len( srcm ); 118 src = (uintptr_t) mbuf_data(srcm); 119 120 dstLen = mbuf_len( dstm ); 121 dst = (uintptr_t) mbuf_data( dstm ); 122 123 for (;;) { 124 if (srcLen < dstLen) { 125 126 // Copy remainder of src mbuf to current dst. 127 BCOPY(src, dst, srcLen); 128 dst += srcLen; 129 dstLen -= srcLen; 130 131 // Move on to the next source mbuf. 132 temp = mbuf_next( srcm ); assert(temp); 133 if(srcm != head) 134 mbuf_free(srcm); 135 srcm = temp; 136 137 srcLen = mbuf_len( srcm ); 138 src = (uintptr_t)mbuf_data(srcm); 139 } 140 else if (srcLen > dstLen) { 141 142 // Copy some of src mbuf to remaining space in dst mbuf. 143 BCOPY(src, dst, dstLen); 144 src += dstLen; 145 srcLen -= dstLen; 146 147 // Move on to the next destination mbuf. 148 temp = mbuf_next( dstm ); assert(temp); 149 dstm = temp; 150 151 dstLen = mbuf_len( dstm ); 152 dst = (uintptr_t)mbuf_data( dstm ); 153 } 154 else { /* (srcLen == dstLen) */ 155 156 // copy remainder of src into remaining space of current dst 157 BCOPY(src, dst, srcLen); 158 159 // Free current mbuf and move the current onto the next 160 temp = mbuf_next( srcm ); 161 if(srcm != head) 162 mbuf_free(srcm); 163 srcm = temp; 164 165 // Do we have any more dest buffers to copy to? 166 if (! mbuf_next ( dstm )) 167 { 168 // nope- hook the remainder of source chain to end of dest chain 169 mbuf_setnext(dstm, srcm); 170 break; 171 } 172 dstm = mbuf_next ( dstm ); 173 174 assert(srcm); 175 dstLen = mbuf_len ( dstm ); 176 dst = (uintptr_t)mbuf_data( dstm ); 177 srcLen = mbuf_len( srcm ); 178 src = (uintptr_t)mbuf_data( srcm ); 179 } 180 } 181} 182 183static const UInt32 kMBufDataCacheSize = 16; 184 185static inline bool analyseSegments( 186 mbuf_t packet, /* input packet mbuf */ 187 const UInt32 mbufsInCache, /* number of entries in segsPerMBuf[] */ 188 const UInt32 segsPerMBuf[], /* segments required per mbuf */ 189 SInt32 numSegs, /* total number of segments */ 190 const UInt32 maxSegs) /* max controller segments per mbuf */ 191{ 192 mbuf_t newPacket; // output mbuf chain. 193 mbuf_t out; // current output mbuf link. 194 SInt32 outSize; // size of current output mbuf link. 195 SInt32 outSegs; // segments for current output mbuf link. 196 SInt32 doneSegs; // segments for output mbuf chain. 197 SInt32 outLen; // remaining length of input buffer. 198 199 mbuf_t in = packet; // save the original input packet pointer. 200 UInt32 inIndex = 0; 201 const uint32_t c_mlen = mbuf_get_mlen(); 202 203 // Allocate a mbuf (non header mbuf) to begin the output mbuf chain. 204 205 if(mbuf_get(MBUF_DONTWAIT, MT_DATA, &newPacket)) 206 { 207 ERROR_LOG("analyseSegments: MGET() 1 error\n"); 208 return false; 209 } 210 211 /* Initialise outgoing packet controls */ 212 out = newPacket; 213 outSize = c_mlen; 214 doneSegs = outSegs = outLen = 0; 215 216 // numSegs stores the delta between the total and the max. For each 217 // input mbuf consumed, we decrement numSegs. 218 // 219 numSegs -= maxSegs; 220 221 // Loop through the input packet mbuf 'in' and construct a new mbuf chain 222 // large enough to make (numSegs + doneSegs + outSegs) less than or 223 // equal to zero. 224 // 225 do { 226 uintptr_t vmo; 227 228 outLen += mbuf_len(in); 229 230 while (outLen > outSize) { 231 // Oh dear the current outgoing length is too big. 232 if (outSize != MCLBYTES) { 233 // Current mbuf is not yet a cluster so promote, then 234 // check for error. 235 236 if(mbuf_mclget(MBUF_DONTWAIT, MT_DATA, &out) || !(mbuf_flags(out) & MBUF_EXT) ) 237 { 238 ERROR_LOG("analyseSegments: MCLGET() error\n"); 239 goto bombAnalysis; 240 } 241 242 outSize = MCLBYTES; 243 244 continue; 245 } 246 247 vmo = (uintptr_t)mbuf_data(out); 248 mbuf_setlen(out, MCLBYTES); /* Fill in target copy size */ 249 doneSegs += (round_page(vmo + MCLBYTES) - trunc_page(vmo)) 250 / PAGE_SIZE; 251 252 // If the number of segments of the output chain, plus 253 // the segment for the mbuf we are about to allocate is greater 254 // than maxSegs, then abort. 255 // 256 if (doneSegs + 1 > (int) maxSegs) { 257 ERROR_LOG("analyseSegments: maxSegs limit 1 reached! %ld %ld\n", 258 doneSegs, maxSegs); 259 goto bombAnalysis; 260 } 261 262 mbuf_t tempmbuf; 263 if(mbuf_get(MBUF_DONTWAIT, MT_DATA, &tempmbuf)) 264 { 265 ERROR_LOG("analyseSegments: MGET() error\n"); 266 goto bombAnalysis; 267 } 268 mbuf_setnext(out, tempmbuf); 269 out = tempmbuf; 270 outSize = c_mlen; 271 outLen -= MCLBYTES; 272 } 273 274 // Compute number of segment in current outgoing mbuf. 275 vmo = (uintptr_t)mbuf_data(out); 276 outSegs = (round_page(vmo + outLen) - trunc_page(vmo)) / PAGE_SIZE; 277 if (doneSegs + outSegs > (int) maxSegs) { 278 ERROR_LOG("analyseSegments: maxSegs limit 2 reached! %ld %ld %ld\n", 279 doneSegs, outSegs, maxSegs); 280 goto bombAnalysis; 281 } 282 283 // Get the number of segments in the current inbuf 284 if (inIndex < mbufsInCache) 285 numSegs -= segsPerMBuf[inIndex]; // Yeah, in cache 286 else { 287 // Hmm, we have to recompute from scratch. Copy code from genPhys. 288 int thisLen = 0, mbufLen; 289 290 vmo = (uintptr_t)mbuf_data(in); 291 for (mbufLen = mbuf_len(in); mbufLen; mbufLen -= thisLen) { 292 thisLen = MIN(next_page(vmo), vmo + mbufLen) - vmo; 293 vmo += thisLen; 294 numSegs--; 295 } 296 } 297 298 // Walk the incoming buffer on one. 299 in = mbuf_next(in); 300 inIndex++; 301 302 // continue looping until the total number of segments has dropped 303 // to an acceptable level, or if we ran out of mbuf links. 304 305 } while (in && ((numSegs + doneSegs + outSegs) > 0)); 306 307 if ( (int) (numSegs + doneSegs + outSegs) <= 0) { // success 308 309 mbuf_setlen(out, outLen); // Set last mbuf with the remaining length. 310 311 // The amount to copy is determine by the segment length in each 312 // mbuf linked to newPacket. The sum can be smaller than 313 // packet->pkthdr.len; 314 // 315 coalesceSegments(packet, newPacket); 316 317 // The initial header mbuf is preserved, its length set to zero, and 318 // linked to the new packet chain. 319 // coalesceSegments() has already freed the mbufs that it coalesced into the newPacket chain. 320 // It also hooked the remaining chain pointed to by "in" to the end of the newPacket chain. 321 // All that remains is to set packet's len to 0 (to "free" the contents that coalesceSegments copied out) 322 // and make it the head of the new chain. 323 324 mbuf_setlen(packet , 0 ); 325 mbuf_setnext(packet, newPacket); 326 327 return true; 328 } 329 330bombAnalysis: 331 332 mbuf_freem(newPacket); 333 return false; 334} 335 336UInt32 IOMbufMemoryCursor::genPhysicalSegments(mbuf_t packet, void *vector, 337 UInt32 maxSegs, bool doCoalesce) 338{ 339 bool doneCoalesce = false; 340 341 if (!packet || !(mbuf_flags(packet) & MBUF_PKTHDR)) 342 return 0; 343 344 if (!maxSegs) 345 { 346 maxSegs = maxNumSegments; 347 if (!maxSegs) return 0; 348 } 349 350 if ( mbuf_next(packet) == 0 ) 351 { 352 uintptr_t src; 353 struct IOPhysicalSegment physSeg; 354 355 /* 356 * the packet consists of only 1 mbuf 357 * so if the data buffer doesn't span a page boundary 358 * we can take the simple way out 359 */ 360 src = (uintptr_t)mbuf_data(packet); 361 362 if ( trunc_page(src) == trunc_page(src + mbuf_len(packet) - 1) ) 363 { 364 physSeg.location = (IOPhysicalAddress) mbuf_data_to_physical((char *)src); 365 if ( physSeg.location ) 366 { 367 physSeg.length = mbuf_len(packet); 368 (*outSeg)(physSeg, vector, 0); 369 return 1; 370 } 371 372 maxSegs = 1; 373 if ( doCoalesce == false ) return 0; 374 } 375 } 376 377 if ( doCoalesce == true && maxSegs == 1 ) 378 { 379 uintptr_t src; 380 uintptr_t dst; 381 mbuf_t m; 382 mbuf_t mnext; 383 mbuf_t out; 384 UInt32 len = 0; 385 struct IOPhysicalSegment physSeg; 386 387 if ( mbuf_pkthdr_len(packet) > MCLBYTES ) return 0; 388 389 m = packet; 390 391 // Allocate a non-header mbuf + cluster. 392 if (mbuf_getpacket( MBUF_DONTWAIT, &out )) 393 return 0; 394 mbuf_setflags( out, mbuf_flags( out ) & ~MBUF_PKTHDR ); 395 dst = (uintptr_t)mbuf_data(out); 396 397 do 398 { 399 src = (uintptr_t)mbuf_data(m); 400 BCOPY( src, dst, mbuf_len(m) ); 401 dst += mbuf_len(m); 402 len += mbuf_len(m); 403 } while ( (m = mbuf_next(m)) != 0 ); 404 405 mbuf_setlen(out , len); 406 407 dst = (uintptr_t)mbuf_data(out); 408 physSeg.location = (IOPhysicalAddress) mbuf_data_to_physical((char *)dst); 409 if (!physSeg.location) 410 { 411 mbuf_free(out); 412 return 0; 413 } 414 physSeg.length = mbuf_len(out); 415 (*outSeg)(physSeg, vector, 0); 416 417 m = mbuf_next(packet); 418 while (m != 0) 419 { 420 mnext = mbuf_next(m); 421 mbuf_free(m); 422 m = mnext; 423 } 424 425 // The initial header mbuf is preserved, its length set to zero, 426 // and linked to the new packet chain. 427 428 mbuf_setlen(packet , 0); 429 mbuf_setnext(packet , out); 430 mbuf_setnext(out , 0); 431 432 return 1; 433 } 434 435 // 436 // Iterate over the mbuf, translating segments were allowed. When we 437 // are not allowed to translate segments then accumulate segment 438 // statistics up to kMBufDataCacheSize of mbufs. Finally 439 // if we overflow our cache just count how many segments this 440 // packet represents. 441 // 442 UInt32 segsPerMBuf[kMBufDataCacheSize]; 443 444tryAgain: 445 UInt32 curMBufIndex = 0; 446 UInt32 curSegIndex = 0; 447 UInt32 lastSegCount = 0; 448 mbuf_t m = packet; 449 450 // For each mbuf in incoming packet. 451 do { 452 vm_size_t mbufLen, thisLen = 0; 453 uintptr_t src; 454 455 // Step through each segment in the current mbuf 456 for (mbufLen = mbuf_len(m), src = (uintptr_t)mbuf_data(m); 457 mbufLen; 458 src += thisLen, mbufLen -= thisLen) 459 { 460 // If maxSegmentSize is atleast PAGE_SIZE, then 461 // thisLen = MIN(next_page(src), src + mbufLen) - src; 462 463 thisLen = MIN(mbufLen, maxSegmentSize); 464 thisLen = MIN(next_page(src), src + thisLen) - src; 465 466 // If room left then find the current segment addr and output 467 if (curSegIndex < maxSegs) { 468 struct IOPhysicalSegment physSeg; 469 470 physSeg.location = (IOPhysicalAddress) mbuf_data_to_physical((char *)src); 471 if ( physSeg.location == 0 ) 472 { 473 return doCoalesce ? 474 genPhysicalSegments(packet, vector, 1, true) : 0; 475 } 476 physSeg.length = thisLen; 477 (*outSeg)(physSeg, vector, curSegIndex); 478 } 479 480 // Count segments if we are coalescing. 481 curSegIndex++; 482 } 483 484 // Cache the segment count data if room is available. 485 if (curMBufIndex < kMBufDataCacheSize) { 486 segsPerMBuf[curMBufIndex] = curSegIndex - lastSegCount; 487 lastSegCount = curSegIndex; 488 } 489 490 // Move on to next imcoming mbuf 491 curMBufIndex++; 492 m = mbuf_next(m); 493 } while (m); 494 495 // If we finished cleanly return number of segments found 496 if (curSegIndex <= maxSegs) 497 return curSegIndex; 498 if (!doCoalesce) 499 return 0; // if !coalescing we've got a problem. 500 501 // If we are coalescing and it is possible then attempt coalesce, 502 if (!doneCoalesce 503 && (UInt) mbuf_pkthdr_len(packet) <= maxSegs * maxSegmentSize) { 504 // Hmm, we have to do some coalescing. 505 bool analysisRet; 506 507 analysisRet = analyseSegments(packet, 508 MIN(curMBufIndex, kMBufDataCacheSize), 509 segsPerMBuf, 510 curSegIndex, maxSegs); 511 if (analysisRet) { 512 doneCoalesce = true; 513 coalesceCount++; 514 goto tryAgain; 515 } 516 } 517 518 assert(!doneCoalesce); // Problem in Coalesce code. 519 packetTooBigErrors++; 520 return 0; 521} 522 523UInt32 IOMbufMemoryCursor::getAndResetCoalesceCount() 524{ 525 UInt32 cnt = coalesceCount; coalesceCount = 0; return cnt; 526} 527 528/* the extern "C" wrappers that follow, are used for binary compatability since 529changing the prototypes from "struct mbuf *" to "mbuf_t" causes the symbol name to change. */ 530 531/********************* class IOMbufBigMemoryCursor **********************/ 532IOMbufBigMemoryCursor * 533IOMbufBigMemoryCursor::withSpecification(UInt32 maxSegSize, UInt32 maxNumSegs) 534{ 535 IOMbufBigMemoryCursor *me = new IOMbufBigMemoryCursor; 536 537 if (me && !me->initWithSpecification(&bigOutputSegment, 538 maxSegSize, maxNumSegs)) { 539 me->release(); 540 return 0; 541 } 542 543 return me; 544} 545 546extern "C" UInt32 _ZN21IOMbufBigMemoryCursor19getPhysicalSegmentsEP4mbufPN14IOMemoryCursor15PhysicalSegmentEm( 547 IOMbufBigMemoryCursor *self, void *packet, struct IOPhysicalSegment *vector, UInt32 numVectorSegments) 548{ 549 return self->getPhysicalSegments((mbuf_t)packet, vector,numVectorSegments); 550} 551 552UInt32 553IOMbufBigMemoryCursor::getPhysicalSegments(mbuf_t packet, 554 struct IOPhysicalSegment *vector, 555 UInt32 numVectorSegments) 556{ 557 return genPhysicalSegments(packet, vector, numVectorSegments, false); 558} 559 560extern "C" UInt32 _ZN21IOMbufBigMemoryCursor31getPhysicalSegmentsWithCoalesceEP4mbufPN14IOMemoryCursor15PhysicalSegmentEm( 561 IOMbufBigMemoryCursor *self, void *packet, struct IOPhysicalSegment *vector, UInt32 numVectorSegments) 562{ 563 return self->getPhysicalSegmentsWithCoalesce((mbuf_t)packet, vector,numVectorSegments); 564} 565 566UInt32 567IOMbufBigMemoryCursor::getPhysicalSegmentsWithCoalesce(mbuf_t packet, 568 struct IOPhysicalSegment *vector, 569 UInt32 numVectorSegments) 570{ 571 return genPhysicalSegments(packet, vector, numVectorSegments, true); 572} 573 574 575/******************* class IOMbufNaturalMemoryCursor ********************/ 576IOMbufNaturalMemoryCursor * 577IOMbufNaturalMemoryCursor::withSpecification(UInt32 maxSegSize, UInt32 maxNumSegs) 578{ 579 IOMbufNaturalMemoryCursor *me = new IOMbufNaturalMemoryCursor; 580 581 if (me && !me->initWithSpecification(&naturalOutputSegment, 582 maxSegSize, maxNumSegs)) { 583 me->release(); 584 return 0; 585 } 586 587 return me; 588} 589 590extern "C" UInt32 _ZN25IOMbufNaturalMemoryCursor19getPhysicalSegmentsEP4mbufPN14IOMemoryCursor15PhysicalSegmentEm( 591 IOMbufNaturalMemoryCursor *self, void *packet, struct IOPhysicalSegment *vector, UInt32 numVectorSegments) 592{ 593 return self->getPhysicalSegments((mbuf_t)packet, vector,numVectorSegments); 594} 595 596UInt32 597IOMbufNaturalMemoryCursor::getPhysicalSegments(mbuf_t packet, 598 struct IOPhysicalSegment *vector, 599 UInt32 numVectorSegments) 600{ 601 return genPhysicalSegments(packet, vector, numVectorSegments, false); 602} 603 604extern "C" UInt32 _ZN25IOMbufNaturalMemoryCursor31getPhysicalSegmentsWithCoalesceEP4mbufPN14IOMemoryCursor15PhysicalSegmentEm( 605IOMbufNaturalMemoryCursor *self, void *packet, struct IOPhysicalSegment *vector, UInt32 numVectorSegments) 606{ 607 return self->getPhysicalSegmentsWithCoalesce((mbuf_t)packet, vector,numVectorSegments); 608} 609 610 611UInt32 612IOMbufNaturalMemoryCursor::getPhysicalSegmentsWithCoalesce(mbuf_t packet, 613 struct IOPhysicalSegment *vector, 614 UInt32 numVectorSegments) 615{ 616 return genPhysicalSegments(packet, vector, numVectorSegments, true); 617} 618 619 620/******************** class IOMbufLittleMemoryCursor ********************/ 621IOMbufLittleMemoryCursor * 622IOMbufLittleMemoryCursor::withSpecification(UInt32 maxSegSize, UInt32 maxNumSegs) 623{ 624 IOMbufLittleMemoryCursor *me = new IOMbufLittleMemoryCursor; 625 626 if (me && !me->initWithSpecification(&littleOutputSegment, 627 maxSegSize, maxNumSegs)) { 628 me->release(); 629 return 0; 630 } 631 632 return me; 633} 634 635extern "C" UInt32 _ZN24IOMbufLittleMemoryCursor19getPhysicalSegmentsEP4mbufPN14IOMemoryCursor15PhysicalSegmentEm( 636 IOMbufLittleMemoryCursor *self, void *packet, struct IOPhysicalSegment *vector, UInt32 numVectorSegments) 637{ 638 return self->getPhysicalSegments((mbuf_t)packet, vector,numVectorSegments); 639} 640 641UInt32 642IOMbufLittleMemoryCursor::getPhysicalSegments(mbuf_t packet, 643 struct IOPhysicalSegment *vector, 644 UInt32 numVectorSegments) 645{ 646 return genPhysicalSegments(packet, vector, numVectorSegments, false); 647} 648 649extern "C" UInt32 _ZN24IOMbufLittleMemoryCursor31getPhysicalSegmentsWithCoalesceEP4mbufPN14IOMemoryCursor15PhysicalSegmentEm( 650 IOMbufLittleMemoryCursor *self, void *packet, struct IOPhysicalSegment *vector, UInt32 numVectorSegments) 651{ 652 return self->getPhysicalSegmentsWithCoalesce((mbuf_t)packet, vector,numVectorSegments); 653} 654 655 656UInt32 657IOMbufLittleMemoryCursor::getPhysicalSegmentsWithCoalesce(mbuf_t packet, 658 struct IOPhysicalSegment *vector, 659 UInt32 numVectorSegments) 660{ 661 return genPhysicalSegments(packet, vector, numVectorSegments, true); 662} 663 664 665/******************** class IOMbufDBDMAMemoryCursor *********************/ 666#ifdef __ppc__ 667 668IOMbufDBDMAMemoryCursor * 669IOMbufDBDMAMemoryCursor::withSpecification(UInt32 maxSegSize, UInt32 maxNumSegs) 670{ 671 IOMbufDBDMAMemoryCursor *me = new IOMbufDBDMAMemoryCursor; 672 673 if (me && !me->initWithSpecification(&dbdmaOutputSegment, 674 maxSegSize, maxNumSegs)) { 675 me->release(); 676 return 0; 677 } 678 679 return me; 680} 681 682extern "C" UInt32 _ZN23IOMbufDBDMAMemoryCursor19getPhysicalSegmentsEP4mbufP17IODBDMADescriptorm( 683IOMbufDBDMAMemoryCursor *self, void *packet, struct IODBDMADescriptor *vector, UInt32 numVectorSegments) 684{ 685 return self->getPhysicalSegments((mbuf_t)packet, vector, numVectorSegments); 686} 687 688UInt32 689IOMbufDBDMAMemoryCursor::getPhysicalSegments(mbuf_t packet, 690 struct IODBDMADescriptor *vector, 691 UInt32 numVectorSegments) 692{ 693 return genPhysicalSegments(packet, vector, numVectorSegments, false); 694} 695 696extern "C" UInt32 _ZN23IOMbufDBDMAMemoryCursor31getPhysicalSegmentsWithCoalesceEP4mbufP17IODBDMADescriptorm( 697IOMbufDBDMAMemoryCursor *self, void *packet, struct IODBDMADescriptor *vector, UInt32 numVectorSegments) 698{ 699 return self->getPhysicalSegmentsWithCoalesce((mbuf_t)packet, vector, numVectorSegments); 700} 701 702 703UInt32 704IOMbufDBDMAMemoryCursor::getPhysicalSegmentsWithCoalesce(mbuf_t packet, 705 struct IODBDMADescriptor *vector, 706 UInt32 numVectorSegments) 707{ 708 return genPhysicalSegments(packet, vector, numVectorSegments, true); 709} 710 711#endif /* __ppc__ */ 712