0
votes

I'm writing code to interface with the NIC in my emulator (QEMU). I need to write the high and low 32-bits of my descriptor array to two separate addresses in memory. I'm struggling to mask (and shift) my raw pointer to write both halves to memory.

I have:

#[repr(align(16))]
struct e1000_rx_desc {
    address : u64,
    length : u16,
    checksum : u16,
    status : u8,
    errors : u8,
    special : u16,
}

And:

#[repr(align(16))]
struct e1000_tx_desc {
    address : u64,
    length : u16,
    cso : u8,
    cmd : u8,
    status : u8,
    css : u8,
    special : u16,
}

An array of these descriptors is stored inside:

pub struct E1000 {
    base : u32,
    rx : [*mut e1000_rx_desc; 32],
    tx : [*mut e1000_tx_desc; 8],
}

And I've been attempting to write to the hardware registers with:

self.write_u32_to_register(Registers::REG_RX_DESC_LO, 0, ((&self.rx as **mut e1000_rx_desc) & 0xFFFFFFFF) as u32);
self.write_u32_to_register(Registers::REG_RX_DESC_HI, 0, ((&self.rx as **mut e1000_rx_desc) >> 32) as u32);

I get the following error:

no implementation for `*const *mut e1000::e1000_rx_desc & {integer}

What is the best way to get access to the raw address so I can manipulate it?

1

1 Answers

2
votes

Pointers can be cast to and from a usize using the as operator:

let x: i32 = 5;
let x_ptr: *const i32 = &x as *const i32;
let x_ptr_addr: usize = x_ptr as usize;
let new_ptr = (x_ptr_addr & 0xffff) as *const i32;