device.rs 12 KB
Newer Older
1
use std::{mem, thread};
Jeremy Soller's avatar
Jeremy Soller committed
2
use std::collections::BTreeMap;
3

Jeremy Soller's avatar
Jeremy Soller committed
4
use netutils::setcfg;
Jeremy Soller's avatar
Jeremy Soller committed
5
use syscall::error::{Error, EACCES, EBADF, EINVAL, EWOULDBLOCK, Result};
Jeremy Soller's avatar
Jeremy Soller committed
6
use syscall::flag::O_NONBLOCK;
7
use syscall::io::{Dma, Mmio, Io, ReadOnly};
8 9 10 11 12
use syscall::scheme::SchemeMut;

#[repr(packed)]
struct Regs {
    mac: [Mmio<u32>; 2],
13 14 15 16 17
    _mar: [Mmio<u32>; 2],
    _dtccr: [Mmio<u32>; 2],
    _rsv0: [Mmio<u32>; 2],
    tnpds: [Mmio<u32>; 2],
    thpds: [Mmio<u32>; 2],
18 19
    _rsv1: [Mmio<u8>; 7],
    cmd: Mmio<u8>,
20
    tppoll: Mmio<u8>,
21 22 23 24 25
    _rsv2: [Mmio<u8>; 3],
    imr: Mmio<u16>,
    isr: Mmio<u16>,
    tcr: Mmio<u32>,
    rcr: Mmio<u32>,
26
    _tctr: Mmio<u32>,
27 28
    _rsv3: Mmio<u32>,
    cmd_9346: Mmio<u8>,
29
    _config: [Mmio<u8>; 6],
30
    _rsv4: Mmio<u8>,
31
    timer_int: Mmio<u32>,
32
    _rsv5: Mmio<u32>,
33 34
    _phys_ar: Mmio<u32>,
    _rsv6: [Mmio<u32>; 2],
35 36
    phys_sts: ReadOnly<Mmio<u8>>,
    _rsv7: [Mmio<u8>; 23],
37 38
    _wakeup: [Mmio<u32>; 16],
    _crc: [Mmio<u16>; 5],
39 40 41
    _rsv8: [Mmio<u8>; 12],
    rms: Mmio<u16>,
    _rsv9: Mmio<u32>,
42
    _c_plus_cr: Mmio<u16>,
43
    _rsv10: Mmio<u16>,
44
    rdsar: [Mmio<u32>; 2],
45 46 47 48
    mtps: Mmio<u8>,
    _rsv11: [Mmio<u8>; 19],
}

49 50 51 52
const OWN: u32 = 1 << 31;
const EOR: u32 = 1 << 30;
const FS: u32 = 1 << 29;
const LS: u32 = 1 << 28;
53 54 55

#[repr(packed)]
struct Rd {
56 57
    ctrl: Mmio<u32>,
    _vlan: Mmio<u32>,
58 59 60 61 62
    buffer: Mmio<u64>
}

#[repr(packed)]
struct Td {
63 64
    ctrl: Mmio<u32>,
    _vlan: Mmio<u32>,
65 66 67 68 69
    buffer: Mmio<u64>
}

pub struct Rtl8168 {
    regs: &'static mut Regs,
Jeremy Soller's avatar
Jeremy Soller committed
70 71 72
    receive_buffer: [Dma<[Mmio<u8>; 0x1FF8]>; 64],
    receive_ring: Dma<[Rd; 64]>,
    receive_i: usize,
73
    transmit_buffer: [Dma<[Mmio<u8>; 7552]>; 16],
74
    transmit_ring: Dma<[Td; 16]>,
Jeremy Soller's avatar
Jeremy Soller committed
75
    transmit_i: usize,
76
    transmit_buffer_h: [Dma<[Mmio<u8>; 7552]>; 1],
Jeremy Soller's avatar
Jeremy Soller committed
77 78 79
    transmit_ring_h: Dma<[Td; 1]>,
    next_id: usize,
    pub handles: BTreeMap<usize, usize>
80 81 82
}

impl SchemeMut for Rtl8168 {
Jeremy Soller's avatar
Jeremy Soller committed
83
    fn open(&mut self, _path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
84
        if uid == 0 {
Jeremy Soller's avatar
Jeremy Soller committed
85 86 87
            self.next_id += 1;
            self.handles.insert(self.next_id, flags);
            Ok(self.next_id)
88 89 90 91 92
        } else {
            Err(Error::new(EACCES))
        }
    }

93 94 95 96 97
    fn dup(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
        if ! buf.is_empty() {
            return Err(Error::new(EINVAL));
        }

Jeremy Soller's avatar
Jeremy Soller committed
98 99 100 101 102 103 104
        let flags = {
            let flags = self.handles.get(&id).ok_or(Error::new(EBADF))?;
            *flags
        };
        self.next_id += 1;
        self.handles.insert(self.next_id, flags);
        Ok(self.next_id)
105 106
    }

Jeremy Soller's avatar
Jeremy Soller committed
107
    fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
108 109
        let flags = self.handles.get(&id).ok_or(Error::new(EBADF))?;

Jeremy Soller's avatar
Jeremy Soller committed
110 111 112
        if self.receive_i >= self.receive_ring.len() {
            self.receive_i = 0;
        }
113

Jeremy Soller's avatar
Jeremy Soller committed
114 115 116
        let rd = &mut self.receive_ring[self.receive_i];
        if ! rd.ctrl.readf(OWN) {
            let rd_len = rd.ctrl.read() & 0x3FFF;
117

Jeremy Soller's avatar
Jeremy Soller committed
118
            let data = &self.receive_buffer[self.receive_i];
119

Jeremy Soller's avatar
Jeremy Soller committed
120 121 122 123
            let mut i = 0;
            while i < buf.len() && i < rd_len as usize {
                buf[i] = data[i].read();
                i += 1;
124
            }
Jeremy Soller's avatar
Jeremy Soller committed
125 126 127 128 129 130 131

            let eor = rd.ctrl.read() & EOR;
            rd.ctrl.write(OWN | eor | data.len() as u32);

            self.receive_i += 1;

            return Ok(i);
132 133
        }

Jeremy Soller's avatar
Jeremy Soller committed
134
        if flags & O_NONBLOCK == O_NONBLOCK {
Jeremy Soller's avatar
Jeremy Soller committed
135 136 137 138
            Ok(0)
        } else {
            Err(Error::new(EWOULDBLOCK))
        }
139 140
    }

Jeremy Soller's avatar
Jeremy Soller committed
141 142 143
    fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
        let _flags = self.handles.get(&id).ok_or(Error::new(EBADF))?;

144
        loop {
Jeremy Soller's avatar
Jeremy Soller committed
145 146 147
            if self.transmit_i >= self.transmit_ring.len() {
                self.transmit_i = 0;
            }
148

Jeremy Soller's avatar
Jeremy Soller committed
149 150 151
            let td = &mut self.transmit_ring[self.transmit_i];
            if ! td.ctrl.readf(OWN) {
                let data = &mut self.transmit_buffer[self.transmit_i];
152

Jeremy Soller's avatar
Jeremy Soller committed
153 154 155 156 157
                let mut i = 0;
                while i < buf.len() && i < data.len() {
                    data[i].write(buf[i]);
                    i += 1;
                }
158

Jeremy Soller's avatar
Jeremy Soller committed
159 160
                let eor = td.ctrl.read() & EOR;
                td.ctrl.write(OWN | eor | FS | LS | i as u32);
161

Jeremy Soller's avatar
Jeremy Soller committed
162
                self.regs.tppoll.writef(1 << 6, true); //Notify of normal priority packet
163

Jeremy Soller's avatar
Jeremy Soller committed
164 165
                while self.regs.tppoll.readf(1 << 6) {
                    thread::yield_now();
166
                }
Jeremy Soller's avatar
Jeremy Soller committed
167 168 169 170

                self.transmit_i += 1;

                return Ok(i);
171 172
            }

173
            thread::yield_now();
174 175 176
        }
    }

Jeremy Soller's avatar
Jeremy Soller committed
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
    fn fevent(&mut self, id: usize, _flags: usize) -> Result<usize> {
        let _flags = self.handles.get(&id).ok_or(Error::new(EBADF))?;
        Ok(id)
    }

    fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
        let _flags = self.handles.get(&id).ok_or(Error::new(EBADF))?;

        let mut i = 0;
        let scheme_path = b"network:";
        while i < buf.len() && i < scheme_path.len() {
            buf[i] = scheme_path[i];
            i += 1;
        }
        Ok(i)
192 193
    }

Jeremy Soller's avatar
Jeremy Soller committed
194 195
    fn fsync(&mut self, id: usize) -> Result<usize> {
        let _flags = self.handles.get(&id).ok_or(Error::new(EBADF))?;
196 197 198
        Ok(0)
    }

Jeremy Soller's avatar
Jeremy Soller committed
199 200
    fn close(&mut self, id: usize) -> Result<usize> {
        self.handles.remove(&id).ok_or(Error::new(EBADF))?;
201 202 203 204 205
        Ok(0)
    }
}

impl Rtl8168 {
206
    pub unsafe fn new(base: usize) -> Result<Self> {
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
        assert_eq!(mem::size_of::<Regs>(), 256);

        let regs = &mut *(base as *mut Regs);
        assert_eq!(&regs.tnpds as *const _ as usize - base, 0x20);
        assert_eq!(&regs.cmd as *const _ as usize - base, 0x37);
        assert_eq!(&regs.tcr as *const _ as usize - base, 0x40);
        assert_eq!(&regs.rcr as *const _ as usize - base, 0x44);
        assert_eq!(&regs.cmd_9346 as *const _ as usize - base, 0x50);
        assert_eq!(&regs.phys_sts as *const _ as usize - base, 0x6C);
        assert_eq!(&regs.rms as *const _ as usize - base, 0xDA);
        assert_eq!(&regs.rdsar as *const _ as usize - base, 0xE4);
        assert_eq!(&regs.mtps as *const _ as usize - base, 0xEC);

        let mut module = Rtl8168 {
            regs: regs,
            receive_buffer: [Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
Jeremy Soller's avatar
Jeremy Soller committed
223 224 225 226 227 228 229 230 231 232 233 234
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
235 236 237 238
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?],
            receive_ring: Dma::zeroed()?,
Jeremy Soller's avatar
Jeremy Soller committed
239
            receive_i: 0,
240 241 242 243 244
            transmit_buffer: [Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
                            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?],
            transmit_ring: Dma::zeroed()?,
Jeremy Soller's avatar
Jeremy Soller committed
245
            transmit_i: 0,
246
            transmit_buffer_h: [Dma::zeroed()?],
Jeremy Soller's avatar
Jeremy Soller committed
247 248 249
            transmit_ring_h: Dma::zeroed()?,
            next_id: 0,
            handles: BTreeMap::new()
250 251 252 253 254 255 256 257 258 259 260
        };

        module.init();

        Ok(module)
    }

    pub unsafe fn irq(&mut self) -> u16 {
        // Read and then clear the ISR
        let isr = self.regs.isr.read();
        self.regs.isr.write(isr);
261 262
        let imr = self.regs.imr.read();
        isr & imr
263 264
    }

Jeremy Soller's avatar
Jeremy Soller committed
265 266 267 268 269 270 271 272 273
    pub fn next_read(&self) -> usize {
        for rd in self.receive_ring.iter() {
            if ! rd.ctrl.readf(OWN) {
                return rd.ctrl.read() as usize & 0x3FFF;
            }
        }
        0
    }

274 275 276 277 278 279 280 281 282
    pub unsafe fn init(&mut self) {
        let mac_low = self.regs.mac[0].read();
        let mac_high = self.regs.mac[1].read();
        let mac = [mac_low as u8,
                    (mac_low >> 8) as u8,
                    (mac_low >> 16) as u8,
                    (mac_low >> 24) as u8,
                    mac_high as u8,
                    (mac_high >> 8) as u8];
283
        print!("{}", format!("   - MAC: {:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));
Jeremy Soller's avatar
Jeremy Soller committed
284
        let _ = setcfg("mac", &format!("{:>02X}-{:>02X}-{:>02X}-{:>02X}-{:>02X}-{:>02X}\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));
285 286 287

        // Reset - this will disable tx and rx, reinitialize FIFOs, and set the system buffer pointer to the initial value
        self.regs.cmd.writef(1 << 4, true);
288 289 290
        while self.regs.cmd.readf(1 << 4) {
            thread::yield_now();
        }
291 292 293

        // Set up rx buffers
        for i in 0..self.receive_ring.len() {
294 295 296
            let rd = &mut self.receive_ring[i];
            let data = &mut self.receive_buffer[i];
            rd.buffer.write(data.physical() as u64);
297
            rd.ctrl.write(OWN | data.len() as u32);
298
        }
Jeremy Soller's avatar
Jeremy Soller committed
299
        if let Some(rd) = self.receive_ring.last_mut() {
300
            rd.ctrl.writef(EOR, true);
301 302 303 304 305 306
        }

        // Set up normal priority tx buffers
        for i in 0..self.transmit_ring.len() {
            self.transmit_ring[i].buffer.write(self.transmit_buffer[i].physical() as u64);
        }
Jeremy Soller's avatar
Jeremy Soller committed
307
        if let Some(td) = self.transmit_ring.last_mut() {
308
            td.ctrl.writef(EOR, true);
309 310 311 312 313 314
        }

        // Set up high priority tx buffers
        for i in 0..self.transmit_ring_h.len() {
            self.transmit_ring_h[i].buffer.write(self.transmit_buffer_h[i].physical() as u64);
        }
Jeremy Soller's avatar
Jeremy Soller committed
315
        if let Some(td) = self.transmit_ring_h.last_mut() {
316
            td.ctrl.writef(EOR, true);
317 318 319 320 321
        }

        // Unlock config
        self.regs.cmd_9346.write(1 << 7 | 1 << 6);

322 323
        // Enable rx (bit 3) and tx (bit 2)
        self.regs.cmd.writef(1 << 3 | 1 << 2, true);
324 325 326 327 328 329 330 331

        // Max RX packet size
        self.regs.rms.write(0x1FF8);

        // Max TX packet size
        self.regs.mtps.write(0x3B);

        // Set tx low priority buffer address
332 333
        self.regs.tnpds[0].write(self.transmit_ring.physical() as u32);
        self.regs.tnpds[1].write((self.transmit_ring.physical() >> 32) as u32);
334 335

        // Set tx high priority buffer address
336 337
        self.regs.thpds[0].write(self.transmit_ring_h.physical() as u32);
        self.regs.thpds[1].write((self.transmit_ring_h.physical() >> 32) as u32);
338 339

        // Set rx buffer address
340 341
        self.regs.rdsar[0].write(self.receive_ring.physical() as u32);
        self.regs.rdsar[1].write((self.receive_ring.physical() >> 32) as u32);
342

343 344 345
        // Disable timer interrupt
        self.regs.timer_int.write(0);

Jeremy Soller's avatar
Jeremy Soller committed
346 347 348 349
        //Clear ISR
        let isr = self.regs.isr.read();
        self.regs.isr.write(isr);

350
        // Interrupt on tx error (bit 3), tx ok (bit 2), rx error(bit 1), and rx ok (bit 0)
351
        self.regs.imr.write(1 << 15 | 1 << 14 | 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1);
352

Jeremy Soller's avatar
Jeremy Soller committed
353 354 355
        // Set TX config
        self.regs.tcr.write(0b11 << 24 | 0b111 << 8);

356
        // Set RX config - Accept broadcast (bit 3), multicast (bit 2), and unicast (bit 1)
357
        self.regs.rcr.write(0xE70E);
358

359 360 361 362
        // Lock config
        self.regs.cmd_9346.write(0);
    }
}