#shkwve: an incomplete kernel/maybe bootloader/UEFI thing/maybe something else if i get bored again

1 messages · Page 2 of 1

untold basin
#

and one port that needs a reset

#

oh right btw

#

i noticed that you do some detection or whatever for usb3?

#

which you dont really need, like at all

short kraken
#

yes you need to

#

yes you do

untold basin
#

no you dont

#

if the device is enabled

#

then its usb3

short kraken
#

you get problems if you reset a usb3 port

untold basin
#

thats what the spec says at least

short kraken
untold basin
#

a USB3 port, after attach, is enabled (PED=1)

#

page 84, 4.3

short kraken
#

uuuh I suppose

untold basin
#

so you don't need to actually check the capabilities

short kraken
#

I didn't actually consider that

untold basin
#

meanwhile, my laziness and lack of desire for more weird structure parsing:

short kraken
#

you have to detect if it's polling tho

#

right?

untold basin
#

its only considered attached when it enters the Enabled state

short kraken
#

right

#

but won't CCS change before PED

#

on usb3

untold basin
#

no

#

i dont think so anyway

#

oh yeah i also found a bug in your ring code

short kraken
#

?

untold basin
#

static void FUSL_xhci_enqueue_impl(struct FUSL_XHCIController *controller, struct FUSL_XHCIQueue const *q, uint32_t dw0, uint32_t dw1, uint32_t dw2, uint32_t dw3) {
  uint32_t volatile *access = (uint32_t volatile *)(q->phys.fusl_address + q->offset);
  access[0] = dw0;
  access[1] = dw1;
  access[2] = dw2;
  // you are missing a fence here
  access[3] = dw3 | q->cycle_state;
  controller->controller.callbacks.pflush(&controller->controller, q->phys, q->offset, 0x10);
}
#

the first 3 writes must go out before the last one

short kraken
#

true, thanks

#

maybe I make that last one a store-release

untold basin
#

not enough

#

hmm actually no

short kraken
#

yes enough

untold basin
#

it is enough

#

but you shouldnt use an atomic

#

wait what invariants does fusl actually require

short kraken
#

?

untold basin
#

like what kind of guarantees does palloc give you

trim seal
#

why does he need a barrier there, its volatile so the compiler is not allowed to reorder those fields

#

or accesses to them rather

untold basin
#

lol

untold basin
trim seal
#

maybe

untold basin
#

volatile accesses are an AM output i believe

#

but either way, cpu reordering

trim seal
#

AM?

untold basin
#

abstract machine

trim seal
#

yeah it doesnt guard against any sort of cpu reordering

short kraken
#

is there any case where pinvalidate wouldn't handle this correctly on a real cpu? @untold basin

#

I can't think of one

#

on arm you're gonna have the entire struct in one cacheline and flush it all at once

untold basin
#

i think you just need two flushes

#

write first 3 fields, flush, write last field, flush

short kraken
#

why isn't what I do correct

#

I don't think it's incorrect in practice

#

because the entire trb is in one cacheline

untold basin
short kraken
#

that all TRBs are 0x10 aligned?

untold basin
#

which is technically not a requirement

short kraken
#

yes, that's what I mean with any real cpu

#

is there any real cpu with less than 0x10 bytes of cacheline?

untold basin
short kraken
#

with XHCI controllers?

#

yeah right

untold basin
#

with a dwc3 because the vendor got the ip on the cheap

short kraken
#

no way

untold basin
#

i wouldnt rule it out tbh

#

just put a fence it doesnt cost you much

short kraken
#

is there a builtin to get the cacheline size

untold basin
short kraken
#

fuck

#

bad lang

untold basin
#

there isnt a zig one either lol

#

so

short kraken
#

I believe there is a stdlib thing

#

not a builtin

untold basin
short kraken
untold basin
short kraken
#

nice then I can write a thing to detect if it's m1 or not

untold basin
#

oh interesting its 128 on x86 too apparantly

short kraken
#

what??

untold basin
untold basin
# short kraken what??

idk man thats what zig source tells me

    // x86_64: Starting from Intel's Sandy Bridge, the spatial prefetcher pulls in pairs of 64-byte cache lines at a time.
    // - https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf
    // - https://github.com/facebook/folly/blob/1b5288e6eea6df074758f877c849b6e73bbb9fbb/folly/lang/Align.h#L107
    //
    // aarch64: Some big.LITTLE ARM archs have "big" cores with 128-byte cache lines:
    // - https://www.mono-project.com/news/2016/09/12/arm64-icache/
    // - https://cpufun.substack.com/p/more-m1-fun-hardware-information
    //
    // powerpc64: PPC has 128-byte cache lines
    // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_ppc64x.go#L9
    .x86_64, .aarch64, .powerpc64 => 128,
#

actually hmm nevermind

short kraken
#

anyways I can't imagine a platform with cachelines smaller than 0x10 and having an XHCI controller

#

so I'll consider it fine

#

but I can add a comment there

untold basin
short kraken
#

but seqcst 🤢

untold basin
#

er, signal fence

short kraken
#

fine

untold basin
#

not thread fence

#

atomic_signal_fence(memory_order_seq_cst)

#

signal fence == compiler reordering

#

and its spec since c11

short kraken
#

store-release feels better at that point

#

than seq cst fence

untold basin
#

i meant signal fence not thread fence

#

the signal fence is a compiler reordering barrier, not a "real" barrier

short kraken
#

wait but that's not enough

#

it could replace the volatile

untold basin
#

ehh it stops almost everything

#
            mfence();
            slot.add(0).write_volatile(values[0]);
            slot.add(1).write_volatile(values[1]);
            slot.add(2).write_volatile(values[2]);
            mfence();
            slot.add(3).write_volatile(values[3] | self.flip);
``` lol i have volatile and also mfence
short kraken
#

ew lol

untold basin
#

mfence is a riscv fence (arm dmb sy iirc)

short kraken
#

what why

#

DMB ST is way enough there

untold basin
#

just to be safe

#

also i doubt its much more expensive

short kraken
#

but just asm("DMB ST"); 🥴

untold basin
#

nah i use it in other places as a store-load fence

#

its fine

#

its not that much worse

lofty hearth
#

hm i should probably add fences to the managarm xhci driver too :^)

untold basin
#

lmfao

#

not needed on x86

#

cuz thats cache coherent

lofty hearth
#

yeah on x86 the 32-bit writes are all atomic anyway

untold basin
#

and if it works on the two arms that are real its fine

short kraken
#

it does work on the arms because the cachelines are large enough

untold basin
#

while they are probably not needed

#

id much rather not have my driver fail inexplicably

lofty hearth
#

well on the pi4 you need to flush after the writes because the pcie controller is not cache coherent

short kraken
#

the possible bug pitust brings up is the 4th store happening before any of the first 3

lofty hearth
#

although you still don't need fences because all the flush completes before the doorbell is rung

short kraken
#

and that won't happen on any real CPU

short kraken
#

right?

lofty hearth
#

ah true yes

short kraken
#

or does it always halt before raising an interrupt/completion TRB

untold basin
lofty hearth
#

not when it stops processing trbs

short kraken
#

okay but it triggers on the first one with the flag, while it's running?

lofty hearth
#

it pushes events for every retired trb with the flag set, and i think the event ring raises the interrupt as long as the event ring is not empty

short kraken
#

yeah it's gotta because keep going since otherwise it would just leave TRBs there unprocessed

untold basin
short kraken
#

yeah so the ring could be running during that then

untold basin
#

actually i do think i have a very hypothetical case where this could fuck up

#

xhci emulation, in a vm, running on a sibling hyperthread

short kraken
#

so it would be an issue if a TRB could be split into multiple cachelines

untold basin
untold basin
# short kraken elaborate

if the vm on a different hyperthread polls the cache line, it can easily see the values out of order

#

because hyperthreads share caches

short kraken
#

let me think

untold basin
#

dont think its super realistic tbh

short kraken
#

if it can happen I will fix it

#

if not I won't

#

I'm starting to think it could be an issue anyways

#

the write to the last dword could finish first anyways

#

and have the cacheline written back

#

because the first 3 stores could depend on a pending load or some shit

#

I think I need the fence, straight up

#

that's not even a contrived example

short kraken
#

q_push(q, uncached_ptr->a, uncached_ptr->b, uncached_ptr->c, 0);

#

here it's even likely the last store happens first

untold basin
#

true

#

yeah

short kraken
#

I will fix it, thanks

#

but why are you unhappy with the store-release

#

I think it's the perfectly scoped thing

#

since it only says "this store needs to wait for all the other stores to finish"

untold basin
#

also its an atomic being used to device stuff

short kraken
#

it does nothing I don't need and everything I need

short kraken
#

not mmio

untold basin
#

also you explicitly permit the memory to be mapped UC

#

in which case atomics wont work

short kraken
#

good catch, thanks

untold basin
#

in the "cause faults" way

short kraken
#

does C11 have a plain store barrier

untold basin
#

a release fence?

short kraken
#

uh...

#

yes

untold basin
#

or just call pflush meme

short kraken
#

eh?

untold basin
untold basin
#

so it's a release fence

short kraken
lofty hearth
#

atomic_thread_fence(memory_order_release);

short kraken
#

anyways how do you feel about the code quality of FUSL @untold basin now that you've read it

lofty hearth
#

and then ig an atomic store?

short kraken
short kraken
lofty hearth
#

UC

untold basin
#

its allowed by the fusl comments

#

so

short kraken
#

yea

#

I want to allow mapping UC even though recommended to map WB

untold basin
#

definitely a lot better than my shitty xhci non-driver

short kraken
#

I take those

untold basin
#

although i call the rings rings instead of queues

#

only thing i call the same as the spec :^)

short kraken
#

call them ring queues :^)

untold basin
#

what about queue rings /j

short kraken
#

that sounds like a ring of queues

untold basin
#

nah its Ring and EventRing

untold basin
#

at least the one specified by the interruptor register at offset 10h is a ring of rings

short kraken
untold basin
#

i dont remember the real name

untold basin
#

because they have different code

short kraken
#

well yes

#

they share no code

#

but they share all the layout

untold basin
#

they dont

short kraken
#

which is a really interesting property

short kraken
untold basin
#

oh well in memory they do

#

but my control struct for them is different

#

because an event ring stores the interruptor associated as well

short kraken
#

why?

#

ah

#

and I assume your event ring doesn't have a dirty flag lol

lofty hearth
untold basin
short kraken
untold basin
#

i just ring the doorbell every time

short kraken
#

producer/consumer? no, producer/event

untold basin
#

woo shit ass drivering

#

if it makes the device do vaguely what i intended it to do its working

lofty hearth
untold basin
lofty hearth
#

well ConsumerRing would obscure what it actually is imo

untold basin
#

just call it Ring and EventRing

#

its only slightly mildly scuffed naming

lofty hearth
#

since it's specifically dealing with the event ring

short kraken
untold basin
#

HostToDevRing and DevToHostRing

#

or OpRing and EventRing

short kraken
#

that's a good one

lofty hearth
short kraken
#

but I don't like the idea of using device

lofty hearth
#

it's just a ring you can push trbs to

short kraken
#

maybe HostToXHCRing

untold basin
#

and XHCToHost

short kraken
#

hah I beat you

untold basin
#

its the obvious name

short kraken
#

way faster

untold basin
#

but dont worry im sure fusl doesnt beat my code for supporting scratch buffers ```rs
let num_scratch_buf = ((hcs2 >> 16) & 0x3E) as usize | (hcs2 >> 27) as usize;
if num_scratch_buf != 0 {
log::error!("{node} xhci: xhc wants {num_scratch_buf} buffers");
return;
}

#

its truly unbeatable

short kraken
#

amazing

untold basin
#

if (wants any) well shit()

short kraken
#

I thought qemu requested a few but didn't use them

#

guess I'm wrong

untold basin
#

no its 0

#

so im cool

lofty hearth
short kraken
#

also literally any hardware will request them

#

so that only works on qemu

untold basin
#

cant even put ram into their xhc's

short kraken
untold basin
#

AAAAAAAAAAH

short kraken
#

you can store entire controller state on disk and resume everything

#

with those

lofty hearth
#

just accidentally restore it with random values to see what happens

short kraken
#

it's very cool and completely useless

lofty hearth
#

also i don't think linux does that

untold basin
#

yeah just reinit the fucking usb devices lol

#

its not like they arent going to rehotplug

short kraken
#

so the spec has to account for that guy

untold basin
short kraken
#

I love how Intel literally got one guy'd when writing the XHCI spec

untold basin
#

it can be seen by the fact that literally every laptop i have kills device power

#

when you suspend

#

so none of this matters anyway!

short kraken
#

"I need to be able to write entire controller state and usb topology to disk and restore after suspend"
"yeah sure that seems perfectly sensible, let's add that"

short kraken
#

always on usb ports are a thing

lofty hearth
#

like changing the bandwidth allocation between different port types

#

on intel controllers you can write to some chipset-specific mmio addresses inside the xhci controller

untold basin
#

ever?

#

but cool ig

short kraken
#

they're nice for charging phones and nothing else

untold basin
#

yeah only reason to have one

short kraken
#

usually marked red

untold basin
#

and a phone is fine with getting reinited

untold basin
#

and i have all typec now

short kraken
untold basin
short kraken
#

true

#

but intel apparently accounts for those

untold basin
#

or get a powerbank enterprise-grade UPS

#

lol

#

and if you need data, well then fuck you

short kraken
#

$7000 enterprise-grade UPS hooked up to $0.3 microcontroller

#

still loses power

untold basin
short kraken
#

good luck finding more than a single cell for that price

untold basin
lofty hearth
untold basin
#

or something

#

ah you cant set the threshold below 8 gbp

short kraken
untold basin
#

yesss

untold basin
#

if you buy 2 you save 10%!

#

(15.5 gbp shipping)

lofty hearth
untold basin
#

lmfao

lofty hearth
untold basin
#

no way qookie is getting a house fire

lofty hearth
#

hasn't caused a fire in the few years it's spent in a drawer so it's fine :^)

#

the cell is probably completely dead though

#

it wasn't great to begin with

untold basin
#

of course i mean its the cheapest powerbank money can buy in bulk from shenzen

#

okay lets figure out the rest of the usb

short kraken
#

if so you got scammed

lofty hearth
#

considering i bought it in person and not over the internet, if you factor in the shipping i think i paid less

untold basin
short kraken
lofty hearth
#

but it was years ago and i don't remember the price

untold basin
#

there are some not fraud listings on amazon as well tho

#

that are like <5gbp

short kraken
untold basin
#

well

short kraken
#

I thought it was exclusively fraud

untold basin
#

not obviously fraud

#

theres also kindles which arent fraud either

#

like yk the official listings

short kraken
#

@untold basin now that I have that fence there I don't need volatile anymore right

#

that's nicer in one way

untold basin
#

idk

short kraken
#
  uint32_t *access = (uint32_t *)(q->phys.fusl_address + q->offset);
  access[0] = dw0;
  access[1] = dw1;
  access[2] = dw2;
  atomic_thread_fence(memory_order_release);
  access[3] = dw3 | q->cycle_state;
  controller->controller.callbacks.pflush(&controller->controller, q->phys, q->offset, 0x10);
short kraken
untold basin
#

volatile is free though

short kraken
#

what would it be allowed to do

untold basin
#

but i have had run ins with compilers doing wild shit before

short kraken
#

it would have to be split into two STRs

untold basin
#

true

short kraken
#

ugh I'm not sure

untold basin
short kraken
#

fuck it you're right

untold basin
#

i managed to make a transfer i think!

#

aaand that looks like the data i got

#

nice

untold basin
#

time to read config

trim seal
#

this guy implemented a usb stack in two days

untold basin
#

3

#

also calling it a stack is a bit of a stretch

#

"jenga tower" fits much better

#

also its massively scuffed

#

so i guess the next step is figuring out which usb device driver to use

untold basin
#

more real descriptor parsing

#

oh, oops, read the wrong descriptor

#

thats the right one

untold basin
#

@short kraken i found another fusl bug

#
static uint32_t calculate_exponent(uint32_t microframes) {
  uint32_t result;
  while((1 << result) < microframes) {
    ++result;
  }
  return result + 3;
}

your calculate_exponent function invokes undefined behavior

#

gcc seems to deal with it fine

#

but clang uses this innovative approach to calculating an exponent: ```x86asm
calculate_exponent:
ret

#

known as "just dont lol"

#

also you write the enable endpoint mask twice, once in FUSL_xhci_reevaluate_endpoint and once in FUSL_xhci_enable_endpoint

trim seal
#

i mean its random so clang is correct

untold basin
trim seal
#

if its so good at figuring out that this is ub why cant it let me know tho

#

instead of silently removing it

#

or is it because of fusl warning level

untold basin
#

it's also not LLVM UB

#

i think

#

hmm maybe it is llvm ub?

#

idk but probably not

vapid echo
untold basin
vapid echo
#

there's no =

#

compilers can already do this

untold basin
#

that isn't an error necessarily

#

also with -Wall -Wextra -Werror it probs would fail

#

yep <source>:4:15: error: variable 'result' is uninitialized when used here [-Werror,-Wuninitialized] 4 | while((1 << result) < microframes) { | ^~~~~~

untold basin
trim seal
#

surely its a solvable problem lol

untold basin
#

especially without impacting compile perf

#

at least afaik

#

oh also i think i managed to accidentally make a HID data request

#

by accident

#

also its kinda annoying that they dont tell you about NAKs

#

because i dont really have a good way of detecting that afaict?

#

hmm is the xhc guaranteed to process shit i tell it in order

#

theres no way right

#

yeah i think there isnt

#

that is really fucking annoying

#

whatever

#

oh i should probably issue the SetConfiguartion thing too

untold basin
#

yeah

short kraken
#

the other api is for every other endpoint

untold basin
#

ah i see i see

#

enable doesn't send the matching command to the xhc

#

which is weird

#

unless im missing something which is very likely

short kraken
#

?

#

which command what now

untold basin
#

after setting all the new parameters for the endpoint

#

like the type and max packet size and whatever else

#

you need to issue a control endpoint trb

#

i think?

short kraken
#

no?

untold basin
#

or at least without it qemu doesnt print the happy line of usb_xhci_ep_enable slotid 1, epid 3

short kraken
#

you're not changing anything except what packet size the controller uses when sending to/from the device

untold basin
#

i mean at some point you have to start making transfers though

#

to like not the control endpoint

short kraken
#

yes?

untold basin
#

and to do that you need to enable the endpoint

#

which requires a control endpoint trb

short kraken
#

if you set the max packet size to 8, a 16 byte data transfer will be split into 2 8 byte packets

untold basin
#

yeah that's different

short kraken
#

I'm pretty sure that's how it works

#

oh what are you saying then

untold basin
#

that your FUSL_xhci_enable_endpoint doesn't enable endpoints

#

it sets up shit to do so, but then doesn't issue the TRB for it

short kraken
#

are you saying there's a control transfer for enabling endpoints?

#

I thought you just set the configuration and get all the endpoints on said configuration

untold basin
#

like you need to tell the XHC to make the endpoint work

short kraken
#

I'm sending the configure endpoint thing, no?

untold basin
#

dont think so?

#

no you arent

short kraken
#
void FUSL_xhci_configure_device(struct FUSL_XHCIPhysicalDevice *dev, uint8_t configuration_value) {
  struct FUSL_XHCIController *controller = (struct FUSL_XHCIController *)dev->pdev.pdev.controller;
  struct FUSL_XHCIInputControlContext *icc = (struct FUSL_XHCIInputControlContext *)dev->pdev.device_phys.fusl_address;
  icc->a |= 1;
  icc->config = configuration_value;
  struct FUSL_XHCISlotContext *isc = (struct FUSL_XHCISlotContext *)(dev->pdev.device_phys.fusl_address + (0x20 << controller->csz));
  isc->context_entries = 31;
  controller->controller.callbacks.pflush(&controller->controller, dev->pdev.device_phys, 0, 0x40 << controller->csz);
  FUSL_xhci_enqueue_command(controller, SPLIT(dev->pdev.device_phys.device_address), 0, ((dev->slot + 1) << 24) | (TRBT_CONFIGURE_ENDPOINT << 10));
}
#

oh

#

I havn't pushed this yet

untold basin
#
void FUSL_xhci_configure_device(struct FUSL_XHCIPhysicalDevice *dev, uint8_t configuration_value) {
  struct FUSL_XHCIController *controller = (struct FUSL_XHCIController *)dev->pdev.pdev.controller;

  struct FUSL_XHCIInputControlContext *icc = (struct FUSL_XHCIInputControlContext *)dev->pdev.device_phys.fusl_address;
  icc->a |= 1;
  icc->config = configuration_value;
  struct FUSL_XHCISlotContext *isc = (struct FUSL_XHCISlotContext *)(dev->pdev.device_phys.fusl_address + (0x20 << controller->csz));
  isc->context_entries = 31;
}

lol

#

yeah okay

#

fair

short kraken
#

okay you're caught up with where I was a few weeks ago then lol

#

I still havn't gone ahead and packaged this into commits yet

untold basin
#

ah okay cool

untold basin
#

right now im trying to get the hid config

#

and im just getting stalls

#

somehow

short kraken
#

you mean the configuration descriptor?

#

if so, what control transfer are you sending?

untold basin
short kraken
#

and issue the SET_CONFIGURATION control transfer (or not set the suppress bit in TRBT_CONFIGURE_ENDPOINT)?

untold basin
short kraken
#

iirc the controller sends it for you if you don't set it

short kraken
#

I can take a look

untold basin
short kraken
#

that sounds like an issue lol

untold basin
short kraken
#

actually

#

I think I'm thinking of address device/SET_ADDRESS

#

not the configuration

#

yeah right, that's correct

#
+  FUSL_control_transfer_flat(pdev, &(struct FUSL_ControlTransfer) {
+    .value = cdesc->configuration_value,
+    .request = 0x09,
+    .type = 0x00,
+    .length = 0,
+    .index = 0,
+  }, 0, 0, true);

that's something I do separately

untold basin
#

oh nvm

#

i think im just sending a garbage control transfer

#

oh yeah

#

i changed the wrong bit

#

yeah

#

okay now im getting the right hid report descriptor

#

contents: ```c
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection (Application)
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x05, 0x07, // Usage Page (Kbrd/Keypad)
0x19, 0xE0, // Usage Minimum (0xE0)
0x29, 0xE7, // Usage Maximum (0xE7)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Page (LEDs)
0x19, 0x01, // Usage Minimum (Num Lock)
0x29, 0x05, // Usage Maximum (Kana)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0xFF, // Logical Maximum (-1)
0x05, 0x07, // Usage Page (Kbrd/Keypad)
0x19, 0x00, // Usage Minimum (0x00)
0x29, 0xFF, // Usage Maximum (0xFF)
0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection

// 63 bytes

#

(qemu usb kbd)

#

and now i have to figure out how to deal with NAKs

#

wait does NAK mean "come back later"?

#

or "i dont have any data"

lofty hearth
#

interrupt eps should automatically deal with NAKs by just trying the transfer later

untold basin
#

does that happen at the xhci level?

lofty hearth
lofty hearth
#

xhci just retries the usb-level transfer after every interval, and the trb chain completes after the first non-NAK response

untold basin
#

oh!!!

#

nice

#

apart from it being pcaped as isochronous

#

that is broken

#

and weird

lofty hearth
#

for isoch eps i think at every interval the device has to respond with data, so a nak would cause the trb to fail

untold basin
#

which is weird

#

also i do have to use the right kind of endpoint right?

#

i cant just make up that it's an isoch now

lofty hearth
#

yeah isoch has some special requirements

#

and bulk vs interrupt differ in the polling behavior i think?

#

not too sure about that

untold basin
#

i see

untold basin
#

i think i have broken event ring code tbh

#

oh i fixed it cool!

#

okay time to make intr endpoints work in a non crappy way

#

probably by doing something which involves queues and unparking or something like that

untold basin
#

or maybe ill figure out how to do multi trait RTTI work

untold basin
#

hmm i still dont know how i should make the xhci transfer api work

#

because transfer can block

#

and rust + async = just no

#

ah i guess fusl just uses callbacks

#

and i dont know how id make that work with the shitty lang im using

#

and my equally shitty driver model

#

i mean i guess i could make my driver model less shitty 😛

#

actually thats probably doable

short kraken
untold basin
short kraken
#

function pointer in the device struct gets called on transfer completion

untold basin
#

yeah i see i see

#

what's the difference between a control transfer and a data transfer?

#

ah hmm

#

wait i dont get it

lofty hearth
#

control transfer sends some data to the device in the setup packet, then sends or receives some data in the data stage, then ends with a status packet

untold basin
#

i see

#

😦 but i wanna

#

polling get report sounds a lot easier than making interrupt transfers work

#

(i probably will need them for cdc anyway lol)

#

the problem is basically that the buffer for a control transfer is effectively owned by the xhc

lofty hearth
#

you can put the setup packet data straight in the trb

#

instead of via a pointer to a buffer

untold basin
#

oh i see

#

thats interesting ig

#

okay yes and hotplug vaguely works

#

im still not sure how to handle transfers yet

#

maybe ill do pubsub?

#

or something idk

short kraken
lofty hearth
#

i thought it was optional

short kraken
#

also qemu ignores this bit for non-setup packets

#

so you will get problems if you try to use it for anything else

short kraken
untold basin
#

interesting

#

i wasnt super careful in implementing the spec because i was mostly copying fusl

#

i should probably fix that then

short kraken
untold basin
#

hmm

#

ok maybe im fine then?

#

ugh async transfers are a pain

#

can the device NAK a control transfer?

short kraken
#

idk

#

but it can stall

untold basin
#

wonderful

short kraken
#

which is even worse

untold basin
#

stall is another way of saying fail right?

short kraken
#

yes but you have to reset the whole endpoint

#

or the device

untold basin
#

or just pretend the device doesnt exist anymore

short kraken
#

yes

#

you can treat it as a fatal device error if you don't care about mass storage

#

mass storage randomly stalls all the time

lofty hearth
#

or well

#

on the xhci side for all eps

short kraken
#

yes

lofty hearth
#

but also on the device side for bulk and intr eps

short kraken
#

lovely

lofty hearth
#

by sending some request on the control pipe

#

also for ls/fs devices anywhere behind a hs hub you need to issue CLEAR_TT_BUFFER for the port the device is on to the closest hs hub

short kraken
#

yeah, super reasonable stuff

#

idk who said usb was convoluted

lofty hearth
#

managarm has all the logic except for the hs hub stuff

#

not sure how well it works since i haven't implemented the usb msd driver handling stalls yet

short kraken
#

yeah I don't have that implemented yet either

#

but I may do it later

lofty hearth
short kraken
#

it wouldn't even be that hard to do either

lofty hearth
#

e.g. if read10 is not supported and it stalls

short kraken
#

each device can just keep track of FUSL_Hub *upstream_hs_hub; which would get inherited from the parent

#

and set to the parent if it's the first non-hs one in the tree

lofty hearth
#

yeah i was thinking of doing that in managarm too

#

each device has a parent hub ptr but it could also just have a parent tt ptr, which would point to the hs hub

short kraken
#

yep exactly

#

I have that setup now too

lofty hearth
#

otoh the hierarchy is at most 6 deep

#

so you can just follow the parents and look for the first hs one

short kraken
#

I mean the route string only has 5 fields so yeah

untold basin
short kraken
#
void FUSL_init_pdev(struct FUSL_Controller *controller, struct FUSL_PhysicalDeviceImpl *pdev, struct FUSL_Hub *parent, uint32_t parent_port, uint32_t speed) {
  pdev->pdev.controller = controller;
  pdev->pdev.parent_hub = parent;
  pdev->pdev.parent_port = parent_port;
  pdev->pdev.speed = speed;
  if(parent) {
    pdev->pdev.depth = parent->device.physical_device->depth + 1;
    pdev->pdev.route_string = parent->device.physical_device->route_string | (pdev->pdev.parent_port << ((parent->device.physical_device->depth) * 5));
    pdev->pdev.root_port = parent->device.physical_device->root_port;
  } else {
    pdev->pdev.depth = 0;
    pdev->pdev.route_string = 0;
    pdev->pdev.root_port = parent_port;
  }
  // ...
}

This function is a great place to do this logic too

untold basin
#

i do care about msc

#

can you send a diff of your local fusl changes?

#

i dont care about nice commits

short kraken
untold basin
#

but it would be nice to have more code i can copy paste

#

and rewrite in rust

#

and also rewrite 10x worse

short kraken
untold basin
#

cool thanks

short kraken
#

can't you just import it?

untold basin
untold basin
#

but where's the fun in that

short kraken
#

the fact that we could share improvements to the codebase

untold basin
#

i also am having this urge to rewrite all my code in c++

short kraken
#

you're welcome to commit to FUSL

#

I can give you master commit access

untold basin
short kraken
#

:O

untold basin
#

the only nontrivial crate i depend on is blake3

#

and rand_chacha

short kraken
#

what do you need blake3 for

untold basin
#

and chrono i guess maybe but i dont super need it

untold basin
#

and hashing files

short kraken
untold basin
untold basin
#

lol

short kraken
#

oh wait nvm that shit uses vectors

short kraken
untold basin
untold basin
short kraken
#

oh

#

just packaged for rust?

untold basin
#

there are two official impls of blake3

short kraken
#

I mean if you use build.zig for your C/C++ project it's pretty nice to depend on shit

untold basin
#

c and rust

short kraken
#

ah kk

short kraken
untold basin
#

i'd much rather port my scuffed ass rust build tool

#

to c++

short kraken
untold basin
#

it also does a bunch of shit i dont want to get rid of

#

like for example it deals with generating the custom debug info format i use

short kraken
#

I mean you can do that in build.zig too

#

but yeah

untold basin
short kraken
#

you can run C/C++ code as a build step to generate it

short kraken
#

as a build step

untold basin
#

id much rather keep shit ass go code

short kraken
#

...

untold basin
#

realistically all id need to do is generate some ninja build file and call it

#

and thats trivial

#

tbh the reason to not switch to c++ is:
(1) rust is usually quite nice
(2) rust enums are very cool
(3) i already have shitloads of pretty complex code

short kraken
#

well 1 is invalid considering why you wanted to switch in the first place

#

if it's not being nice to you then who cares what it usually is

untold basin
#

true

#

it usually does work though

#

for me

#

its just annoying in some cases

short kraken
#

and that's why I'll never use it

#

I always do the funky shit

#

I never write normal code lol

untold basin
#

true

#

but there are some nice things in rust

#

my favorite cursed thing is the meme i do for buffers

short kraken
#

?

untold basin
#

so rust has those stupid rules around mutability or whatever

#

like you cant have two &mut Ts or whatever

#

but i want to

#

so

#

i have some scuffed code that can make a &Buffer out of &mut [u8]

#

and the &Buffer is mutable, you can write to it

#

and i think it doesnt even invoke ub most of the time

#

anyway im now gonna try to figure out how to make async usb shit work in a way that isnt turbo pain

#

are transfers guaranteed to occur in order?

untold basin
#

hmm maybe i should make an iokit-style tree instead of my shitty current tree

untold basin
#

maybe i should make a different subsystem for dealing with usb devices

#

it doesnt compose well but its easyyyy

#

meh its fine ill just do some other random shit

#

that is only vaguely functional

short kraken
untold basin
#

ah cool

short kraken
#

basically each ep is its own queue

untold basin
#

how bad is it if i only support one queued transfer per endpoint meme

short kraken
#

for mass storage you basically have to do that anyways

#

it's pretty shit for ethernet adapters if you wanna do those

untold basin
#

so i guess i need to handle that, so, fuck

#

do MSC devices only stall their bulk endpoints?

short kraken
#

I'd even say it's easier to implement ethernet adapters if you do multiple at the same time

short kraken
short kraken
#

it's literally a valid ethernet impl to have an unchecked ring buffer of packets to send

#

and to just overwrite things if you run out of space

#

this is what FUSL will do

untold basin
#

dropping is fine tho

short kraken
#

but that requires a conditional :^)

#

actually maybe that's better, could tell the host the packet got dropped

#

so that the caller can do things differently if it wants to

untold basin
#

okay time to parse a HID report

#

how hard can it be

short kraken
untold basin
#

there are so many interesting bits in the hid report descriptor

#

why would i hardcode it

#

the usb implementers forum spent lots of time on it

#

okay so how do i hardcode it anyway

short kraken
untold basin
#

nah i will try parsing HID

short kraken
#

you're crazy

#

make sure to get the units right

untold basin
#

or can i be the first

short kraken
#

I don't know of one

#

I plan to do a very small subset of proper parsing in FUSL

untold basin
#

now i want to do proper parsing even more

short kraken
#

...

untold basin
#

what the actual fuck

short kraken
untold basin
#

i'll probably end up doing some scuffed bytecoded compiler

untold basin
short kraken
#

yes

untold basin
#

for what?

short kraken
#

idk if you have a USB potentiometer

untold basin
#

i dont have a usb potentiometer

#

i have a usb keyboard, mouse and tablet

short kraken
#

obviously all this needs to be part of the same spec as keyboards and mice

untold basin
#

honestly the thing that is the most annoying is that they shoved fahrenheit as a legal unit

#

like fuck off

#

the rest are easy enough, you can just do some fixed point math to remap it to SI

short kraken
#

the spec should explicitly say it's not

untold basin
#

wait

#

whattttttttttttttttt

#

is it an aspirational unit?

#

or what the fuck are you telling me

short kraken
#

no I'm saying that's what I think it should do

untold basin
#

oh yes

#

it should

#

the annoying thing isnt that its a shitty unit

#

though it is

short kraken
#

"invalid unit, use real unit"

untold basin
#

the issue is that its not a fucking absolute unit

#

eh

#

thats probably still solvable

#

if i do deal with units ill definitely turn everything into SI

#

and ill have pixels per meter

short kraken
untold basin
#

lol

short kraken
#

good

short kraken
untold basin
#

if they just used degrees rankine

#

which is kelvin but with fahrenheit

#

that would be like fine

#

you can apply a multiple or whatever to get SI

#

or hear me out

#

make oems turn units into fucking SI

#

and turn it back into customary units or whatever other pain the user wants based on system locale

short kraken
untold basin
#

okay anyway

#

back to having fun in hid land

#

"fun"

#

hmm so i kinda got bored of reading the hid spec

#

does putting the device in boot mode make it do normal shit

short kraken
#

boot means it has a predefined layout

untold basin
#

cool

#

does it work for all devices?

short kraken
#

nope

#

subclass == 1

untold basin
#

ah

#

annoying

short kraken
#

and protocol tells you if keyboard (1) or mouse (2)

#

modifier keys are byte 0

#

each bit is lctrl, lshift, lalt, lsuper, then repeated for right

#

second byte is unused

#

rest (6) of the bytes are the currently pressed scancodes

#

if either of those contain 0xFF the packet should be ignored, the keyboard couldn't give you the data

#

usually because of too many keys pressed

#

that's the entire protocol

untold basin
#

oh okay

#

thats not that bad

short kraken
#

for mouse you have 1 byte of buttons, lmb rmb mmb, then 2 signed bytes for x and y respectively

untold basin
#

yeah but it cant do tablet so its useless anyway :^)

short kraken
#

you could do parsing only for tablets

untold basin
#

eh

#

might as well do all parsing

short kraken
#

okay...

#

also I have no idea how to map HID tablet touchscreens to physical displays

#

if you figure that out then please tell me

untold basin
#

the panel size is in EDID

#

i dont have a touchscreen though

short kraken
#

ugh but what if you have two

untold basin
#

two what? two touchscreens?

short kraken
#

yes

#

two of the same model

untold basin
#

i suspect you tell the user "well fuck u" and choose randomly

#

hmm my friend has a laptop with a touchscreen iirc so maybe i should ask them to dump the hid report

#

or maybe even two touchscreens idr

untold basin
short kraken
#

I do have a touchscreen laptop

#

if you want it

untold basin
#

yes i do

short kraken
#

sure

untold basin
#

please send

short kraken
#

I assume you find it with some AML shit

#

I don't think I spotted anything like that in the HID

untold basin
#

well now that you say it

#

i want the acpi dump too

short kraken
#

sure

short kraken
#

yep

#

that looks correct

untold basin
#

thats from an online tool

#

so its obviously correct lol

short kraken
#

I mean that it doesn't look corrupt

untold basin
#

oh yeah

short kraken
trim seal
#

over i2c

#

TPD0

short kraken
trim seal
#

Both your touchpad and screen

short kraken
#

ah

trim seal
#

TPD0 and TPL1

untold basin
#

see, hid parsing is so easy!

trim seal
#

Imagine if hid bytecode was a subset of aml

untold basin
#

oh god

#

that would be so horrible

trim seal
#

lmao

untold basin
#

its already bad

#

dont make it worse plz

trim seal
#

why is it bad? never looked into it

untold basin
#

its weird

#

its not THAT bad i guess?

#

the problem is that if you smushed aml into it

#

youd have the aml problems

#

hid is not really a programming language

trim seal
#

is it turing complete?

untold basin
#

nope

trim seal
#

thank god lol

untold basin
#

yes

untold basin
#

more parsing!

#

had an off by one, this is corrected

#

this is even more correct

#

this is a usb tablet

#

actually, here is the mouse again, with an is_abs field added

#

and that's a usb keyboard

trim seal
#

can it be parsed as lookup_tableidx?

untold basin
#

not really no

#

i mean kinda?

trim seal
#

why is that?

untold basin
trim seal
#
type = read_type(data)
length = read_length(data)
lookup_table[type](ctx, length)
data += length

?

#

would that work

trim seal
#

how do u do it

untold basin
#

roughly: rs loop { let item_tdat = read_item() match item_tdat.typ { 0 => handle item x(), 1 => handle item y(), } }

trim seal
#

so kinda same thing just switch instead

#

is type a u8?

untold basin
#

its two u8s iirc

#

yeah

#
        let (size, typ, tag) = if ctrl == 0xfe {
            // long item
            let size = self.byte()?;
            let tag = self.byte()?;
            (size, 3, tag)
        } else {
            // short item
            let size = ctrl & 0x3;
            let typ = (ctrl >> 2) & 0x3;
            let tag = ctrl >> 4;
            (size, typ, tag)
        };
trim seal
#

like sub-type?

untold basin
#

typ+tag are the type

trim seal
#

ah

untold basin
#

note that i havent seen anything with typ=3

#

and typ=3 is invalid for a short item

trim seal
#

interesting

untold basin
#

so lol

trim seal
#

looks like an interesting format ig

trim seal
#

and big ones might have variable layout and size, whereas small ones are mostly hardcoded

#

i had to invent a vm to parse them

untold basin
#

yeah this is pretty common

trim seal
#
static const struct uacpi_resource_convert_instruction convert_irq_to_native[] = {
    OP(PACKED_ARRAY_16, AML_F(irq, irq_mask), NATIVE_F(irq, irqs),
       ARG2(NATIVE_O(irq, num_irqs))),
    OP(SKIP_IF_AML_SIZE_LESS_THAN, ARG0(3), IMM(6)),
        OP(SET_TO_IMM, NATIVE_F(irq, length_kind),
           IMM(UACPI_RESOURCE_LENGTH_KIND_FULL)),
        OP(BIT_FIELD_1, AML_F(irq, flags), NATIVE_F(irq, triggering), IMM(0)),
        OP(BIT_FIELD_1, AML_F(irq, flags), NATIVE_F(irq, polarity), IMM(3)),
        OP(BIT_FIELD_1, AML_F(irq, flags), NATIVE_F(irq, sharing), IMM(4)),
        OP(BIT_FIELD_1, AML_F(irq, flags), NATIVE_F(irq, wake_capability), IMM(5)),
        END(),
    OP(SET_TO_IMM, NATIVE_F(irq, length_kind),
       IMM(UACPI_RESOURCE_LENGTH_KIND_ONE_LESS)),
    OP(SET_TO_IMM, NATIVE_F(irq, triggering), IMM(UACPI_TRIGGERING_EDGE)),
    END(),
};

LULW

untold basin
#

holy shit you dont have to do that much scuffed shit

#

have you considered writing a DSL for uacpi btw?

#

you have a ton of bytecode

trim seal
#

yeah a DSL would work really well

untold basin
#

and i feel like a proper dsl could make it somewhat more maintainable

trim seal
#

i even considered autogenerating bytecode handlers from python

#

from some description lang

#

something for the future i guess

#

ACPICA is even worse, they have sparse lookup tables depending on operand type and count and switches per matching op inside each handler that do unrelated things

#

and obviously no microcode so everything is duplicated

#

some aml ops in uacpi dont even have a native handler because there's no need, and ones that do have only actual logic related stuff inside

trim seal
#

which are used on modern real hw so acpica breaks there

untold basin
#

@short kraken i managed to get parsing working for your touchscreen's descriptor too

#

oh huh there is a (3,7) entry in there

#

and a (0,2)

#

0,2 is not in the spec

#

i think 3,7 is broken parsing logic

#

anyway back to the land of things im planning to support in the near future

#

i.e. not digitizers

trim seal
untold basin
#

its a long entry

#

which shouldnt happen?

#

or at least i didnt see the spec define it

#

but yeah idk

trim seal
#

like the hid descriptor is broken?

untold basin
#

yeah probably?

trim seal
#

lol

#

aml 2.0

untold basin
#

actually probably not

#

it parses on linux

trim seal
#

maybe linux skips unknown entries

untold basin
#

i think i have broken parsing

#

oh yeah

#

i do

#

nvm lol

#

now it works :^)

trim seal
#

whats the actual thing?

untold basin
#

what thing?

trim seal
#

that it was supposed to be

untold basin
#

the bug?

#

oh i was parsing entries that were 4 bytes long as if they were 3 bytes long

trim seal
#

lol

untold basin
#

the entry was a "logical maximum at 2147483646" entry

#

which is 5 bytes total

#

and 4 bytes of payload

#

okay lets actually do something with the parse result

short kraken
#

why are there 2 x/y values

trim seal
#

multiple fingers?

short kraken
#

there are multiple fingers at the top level

#

each finger has 2 x/y coords, a width and height

trim seal
#

maybe startx endx

short kraken
#

but it has a width/height?

trim seal
#

lol

#

who knows

untold basin
#

hmm maybe its a bug in my code actually

#

no it seems like two x and two y is correct

short kraken
#

it's weird

untold basin
short kraken
#

I guess I should log some reports

#

so that we can see what it looks like

untold basin
#

yes

#

wireshark meme

#

or rawhid

short kraken
#

but that would require me to get off the shitter

untold basin
#

lol fair

#

usb keyboard hid shit works

#

oh wait

#

no it doesnt

#

grrr

#

wrong byte order

#

ok yeah its big endain

#

obviously

trim seal
#

why did they make it big endian

untold basin
#

no fucking clue

trim seal
#

so annoying when they do it lol

#

fdt as well

untold basin
#

oh also the metadata shit is little

#

obviously

#

its just the actual events that are big

untold basin
#

it was a powerpc format

trim seal
#

i guess yeah

untold basin
#

and they decided to byteswap everything instead of making it little endian

trim seal
#

worst offender is iso9660

untold basin
#

usb is little

trim seal
#

they have both fields duplicated

untold basin
#

ok cool anyway

trim seal
#

and of course half the generators just generate the big endian ones incorrectly so everyone uses the little endian ones

untold basin
#

@short kraken now i have usb hid report parsing done properly so basically im the best os

trim seal
#

not even boot protocol damn

untold basin
#

nope