drivers/gpu/drm/drm_panic_qr.rs

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/drm_panic_qr.rs

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/drm_panic_qr.rs
Extension
.rs
Size
34298 bytes
Lines
1017
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct DecFifo {
    decimals: [u8; MAX_FIFO_SIZE],
    len: usize,
}

// On arm32 architecture, dividing an `u64` by a constant will generate a call
// to `__aeabi_uldivmod` which is not present in the kernel.
// So use the multiply by inverse method for this architecture.
fn div10(val: u64) -> u64 {
    if cfg!(target_arch = "arm") {
        let val_h = val >> 32;
        let val_l = val & 0xFFFFFFFF;
        let b_h: u64 = 0x66666666;
        let b_l: u64 = 0x66666667;

        let tmp1 = val_h * b_l + ((val_l * b_l) >> 32);
        let tmp2 = val_l * b_h + (tmp1 & 0xffffffff);
        let tmp3 = val_h * b_h + (tmp1 >> 32) + (tmp2 >> 32);

        tmp3 >> 2
    } else {
        val / 10
    }
}

impl DecFifo {
    fn push(&mut self, data: u64, len: usize) {
        let mut chunk = data;
        for i in (0..self.len).rev() {
            self.decimals[i + len] = self.decimals[i];
        }
        for i in 0..len {
            self.decimals[i] = (chunk % 10) as u8;
            chunk = div10(chunk);
        }
        self.len += len;
    }

    /// Pop 3 decimal digits from the FIFO
    fn pop3(&mut self) -> Option<(u16, usize)> {
        if self.len == 0 {
            None
        } else {
            let poplen = 3.min(self.len);
            self.len -= poplen;
            let mut out = 0;
            let mut exp = 1;
            for i in 0..poplen {
                out += u16::from(self.decimals[self.len + i]) * exp;
                exp *= 10;
            }
            Some((out, NUM_CHARS_BITS[poplen]))
        }
    }
}

struct SegmentIterator<'a> {
    segment: &'a Segment<'a>,
    offset: usize,
    decfifo: DecFifo,
}

impl Iterator for SegmentIterator<'_> {
    type Item = (u16, usize);

    fn next(&mut self) -> Option<Self::Item> {
        match self.segment {
            Segment::Binary(data) => {
                if self.offset < data.len() {
                    let byte = u16::from(data[self.offset]);
                    self.offset += 1;
                    Some((byte, 8))
                } else {
                    None
                }
            }
            Segment::Numeric(data) => {
                if self.decfifo.len < 3 && self.offset < data.len() {
                    // If there are less than 3 decimal digits in the fifo,
                    // take the next 7 bytes of input, and push them to the fifo.
                    let mut buf = [0u8; 8];
                    let len = 7.min(data.len() - self.offset);
                    buf[..len].copy_from_slice(&data[self.offset..self.offset + len]);
                    let chunk = u64::from_le_bytes(buf);
                    self.decfifo.push(chunk, BYTES_TO_DIGITS[len]);
                    self.offset += len;
                }
                self.decfifo.pop3()
            }
        }

Annotation

Implementation Notes