123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- (**
- * UsbTdAllocator
- *
- * This module provides common TD allocation code for UsbOhci and UsbUhci.
- * In those USB 1.0 controllers, all data structures are 16-byte aligned and their size
- * is less than or equal to 16 bytes.
- *)
- MODULE UsbTdAllocator; (** AUTHOR "Timothée Martiel"; PURPOSE "Common TD allocation code for UsbUhci and UsbOhci"; *)
- CONST
- (** Size of each individual buffer. Must be a multiple of BlockSize * 32. *)
- TdBufferSize = 4096;
- (** Size of an allocation block. *)
- BlockSize = 16;
- BitmaskSize = TdBufferSize DIV (BlockSize * 32);
- TYPE
- TdBuffer = POINTER TO RECORD
- buffer: ARRAY TdBufferSize OF CHAR;
- used: ARRAY BitmaskSize OF SET;
- next: TdBuffer;
- END;
- Allocator * = OBJECT
- VAR
- buffers: TdBuffer;
- PROCEDURE Allocate * (): ADDRESS;
- VAR
- buf: TdBuffer;
- count, tdIn, tdOut: LONGINT;
- (** Allocate a new TD buffer and mark as used the last 32-byte block before a 4kB page boundary. *)
- PROCEDURE AllocateBuffer;
- VAR
- buf: TdBuffer;
- count: LONGINT;
- BEGIN
- (* No buffer found: allocate a new one *)
- NEW(buf);
- buf.next := buffers;
- buffers := buf;
- count := 0;
- END AllocateBuffer;
- BEGIN
- (* Find a buffer with enough room. *)
- buf := buffers;
- LOOP
- IF buf = NIL THEN
- AllocateBuffer;
- buf := buffers;
- ASSERT(buf # NIL)
- END;
- count := 0;
- tdOut := 0;
- FOR tdOut := 0 TO BitmaskSize - 1 DO
- FOR tdIn := 0 TO 31 DO
- IF ~(tdIn IN buf.used[tdOut]) THEN
- INCL(buf.used[tdOut], tdIn);
- RETURN ADDRESSOF(buf.buffer[(tdOut * 32 + tdIn) * BlockSize])
- END
- END
- END;
- buf := buf.next
- END;
- (* We should not get to this point *)
- ASSERT(buf # NIL);
- END Allocate;
- PROCEDURE Free * (td: ADDRESS(*; size: LONGINT*));
- VAR
- buf: TdBuffer;
- adr: ADDRESS;
- slot, tdIn, tdOut: LONGINT;
- BEGIN
- (*ASSERT(size MOD BlockSize = 0);*)
- buf := buffers;
- LOOP
- IF buf = NIL THEN EXIT END;
- adr := ADDRESSOF(buf.buffer[0]);
- IF (adr <= td) & (td <= adr + TdBufferSize) THEN EXIT END;
- buf := buf.next
- END;
- ASSERT(buf # NIL); (* Not a TD *)
- slot := (td - adr) DIV BlockSize;
- tdOut := slot DIV 32;
- tdIn := slot MOD 32;
- (*FOR i := 0 TO (size DIV BlockSize) - 1 DO
- IF tdIn + i < 32 THEN*)
- ASSERT(tdIn (*+ i*) IN buf.used[tdOut]);
- EXCL(buf.used[tdOut], tdIn (*+ i*))
- (*ELSE
- ASSERT(tdIn + i - 32 IN buf.used[tdOut + 1]);
- EXCL(buf.used[tdOut + 1], tdIn + i - 32)
- END
- END;*)
- END Free;
- END Allocator;
- END UsbTdAllocator.
|