2012/2/19 Peter Maydell <peter.mayd...@linaro.org>:
> On 18 February 2012 16:19, Wei Yang <weiyang.ker...@gmail.com> wrote:
>> I am reading the code in ohci_service_td().
>>
>> There is a calculation of the length of the buffer.
>>
>>        if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) {
>>            len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff);
>>        } else {
>>            len = (td.be - td.cbp) + 1;
>>        }
>>
>> I am curious about the first case.
>> So the td.be could be less than the tb.cbp?
>
Thanks Peter.

> Yes. See the OHCI spec:
> ftp://ftp.compaq.com/pub/supportinformation/papers/hcir1_0a.pdf
> and specifically section 4.3: the data buffer described by a
> TD may span two separate physically disjoint pages. The exact

I see this sentence. So this sentence means.
For example, I have
page 1
page 2
page 3
which contains the content of the TD. (In the guest I think.)

TD buffer could locate at page1 and page 3, without touching page 2?
And I am wondering, the buffer in the guest is page aligned or not?

In struct OHCIState, there is the usb_buf[8192].
I think this is the maximum packet size defined in the MPS field in the ED.
The size is exactly 2 pages, if the page is 4K.

This usb_buf is the buffer in the HC I think, so each time we use ohci_copy_td()
to get the content from the guest and put it in usb_buf.

Now come to my previous question again.
tb.cbp and tb.be is pointing to the address in the guest.
This means
tb.be may point to page 1
while
tb.cbp may point to page 3?

So tb.cbp > tb.be?

> page crossing behaviour is described more specifically in
> section 4.3.1.3.1. (We don't implement it quite as described
> there because we try to handle the whole data buffer at once
> rather than byte-by-byte, but the effect is the same. See
> also the code later on in the function under 'Transmission
> succeeded' which updates td.cbp to the right value if we only
> managed to send part of the data.)
>
I quoted it from the specification.
===========================================================
If during the data transfer the buffer address contained in the HC’s
working copy of
CurrentBufferPointer crosses a 4K boundary, the upper 20 bits of
Buffer End are copied to the
working value of CurrentBufferPointer causing the next buffer address
to be the 0th byte in the
same 4K page that contains the last byte of the buffer (the 4K
boundary crossing may occur
within a data packet transfer.)
===========================================================

As I asked before, if the buffer is paged aligned, the
CurrentBufferPointer is pointing to the
beginning of one page.
Since the MPS is 8K, so Buffer End just has two cases.
     Page A                       Page B
  |-----------------------|    |-----------------------|
  ^                      ^                              ^
  |                       | case 1                   | case 2
cbp                   be                            be

PageA and PageB are disjoint pages.

For case 1, it is easy to calculate the buffer size.

For case 2, since the page maybe disjoint, so after copy the first page,
cbp is set to the start of the next page.  If we just calculate
cbp = cbp + 0x1000
this may not be the start address of PageB.

I think my assumption is based on
1. buffer size is less than the MPS, which is 8k.
2. the cbp is page aligned.

Hmm.... I looked at the code again.

len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff);
If cbp is page aligned, then no need to do (td.cbp & 0xfff)?

> -- PMM



-- 
Richard Yang
Help You, Help Me

Reply via email to