- tUHCI_TD *td = UHCI_int_GetTDFromPhys(link);
- int byte_count = (td->Control&0x7FF)+1;
- LOG("link = 0x%x, td = %p, byte_count = %i", link, td, byte_count);
- // Handle non-page aligned destination
- // TODO: This will break if the destination is not in global memory
- if(td->_info.bCopyData)
+ // Get size of transfer
+ byte_count = (td->Control & 0x7FF)+1;
+
+ // Handle non page-aligned destination (with a > 32-bit paddr)
+ if(info->FirstPage)
+ {
+ char *src, *dest;
+ int src_ofs = td->BufferPointer & (PAGE_SIZE-1);
+ src = (void *) MM_MapTemp(td->BufferPointer);
+ dest = (void *) MM_MapTemp(info->FirstPage);
+ // Check for a single page transfer
+ if( byte_count + info->Offset <= PAGE_SIZE )
+ {
+ LOG("Single page copy %P to %P of %p",
+ td->BufferPointer, info->FirstPage, td);
+ memcpy(dest + info->Offset, src + src_ofs, byte_count);
+ }
+ else
+ {
+ // Multi-page
+ LOG("Multi page copy %P to (%P,%P) of %p",
+ td->BufferPointer, info->FirstPage, info->SecondPage, td);
+ int part_len = PAGE_SIZE - info->Offset;
+ memcpy(dest + info->Offset, src + src_ofs, part_len);
+ MM_FreeTemp( (tVAddr)dest );
+ dest = (void *) MM_MapTemp(info->SecondPage);
+ memcpy(dest, src + src_ofs + part_len, byte_count - part_len);
+ }
+ MM_FreeTemp( (tVAddr)src );
+ MM_FreeTemp( (tVAddr)dest );
+ }
+
+ // Don't mark as inactive, the check should do that
+ if( info->Callback == INVLPTR )