| 227 | } |
| 228 | |
| 229 | static void usb_write(uint16_t pio, uint8_t value, bool poke) { |
| 230 | uint8_t index = pio >> 2; |
| 231 | uint8_t bit_offset = (pio & 3) << 3; |
| 232 | if (unlikely(usb.regs.dma_ctrl >> 31 & usb.regs.phy_tmsr) && index >= (0x044 >> 2) && index < (0x1C8 >> 2)) { |
| 233 | return; |
| 234 | } |
| 235 | (void)poke; |
| 236 | switch (index) { |
| 237 | case 0x010 >> 2: // USBCMD - USB Command Register |
| 238 | write8(usb.regs.hcor.usbcmd, bit_offset, value & 0xFF0BFF >> bit_offset); // W mask (V or RO) |
| 239 | usb.regs.hcor.usbsts &= ~0xD000; |
| 240 | usb.regs.hcor.usbsts |= ~usb.regs.hcor.usbcmd << 12 & 0x1000; |
| 241 | usb.regs.hcor.usbsts |= usb.regs.hcor.usbcmd << 10 & 0xC000; |
| 242 | if ((uint32_t)value << bit_offset & 2) { |
| 243 | usb_host_reset(); |
| 244 | } |
| 245 | break; |
| 246 | case 0x014 >> 2: // USBSTS - USB Status Register |
| 247 | usb.regs.hcor.usbsts &= ~((uint32_t)value << bit_offset & 0x3F); // WC mask (V or RO) |
| 248 | break; |
| 249 | case 0x018 >> 2: // USBINTR - USB Interrupt Enable Register |
| 250 | write8(usb.regs.hcor.usbintr, bit_offset, value & 0x3F >> bit_offset); // W mask (V) |
| 251 | break; |
| 252 | case 0x01C >> 2: // FRINDEX - Frame Index Register |
| 253 | write8(usb.regs.hcor.frindex, bit_offset, value & 0x3FFF >> bit_offset); // W mask (V) |
| 254 | break; |
| 255 | case 0x024 >> 2: // PERIODICLISTBASE - Periodic Frame List Base Address Register |
| 256 | write8(usb.regs.hcor.periodiclistbase, bit_offset, value & ~0xFFF >> bit_offset); // V mask (W) |
| 257 | break; |
| 258 | case 0x028 >> 2: // ASYNCLISTADDR - Current Asynchronous List Address Register |
| 259 | write8(usb.regs.hcor.asynclistaddr, bit_offset, value & ~0x1F >> bit_offset); // V mask (W) |
| 260 | break; |
| 261 | case 0x030 >> 2: // PORTSC - Port Status and Control Register |
| 262 | usb.regs.hcor.portsc[0] &= ~((uint32_t)value << bit_offset & 0x2A); // WC mask (V or RO or W) |
| 263 | write8(usb.regs.hcor.portsc[0], bit_offset, value & 0x1F0000 >> bit_offset); // W mask (RO) |
| 264 | break; |
| 265 | case 0x040 >> 2: // Miscellaneous Register |
| 266 | write8(usb.regs.miscr, bit_offset, value & 0xFFF >> bit_offset); // W mask (V) |
| 267 | break; |
| 268 | case 0x044 >> 2: // unknown |
| 269 | write8(usb.regs.rsvd2[0], bit_offset, value & 0x7FFF >> bit_offset); // W mask (V) |
| 270 | break; |
| 271 | case 0x048 >> 2: // unknown |
| 272 | write8(usb.regs.rsvd2[1], bit_offset, value & 0xFFF >> bit_offset); // W mask (V) |
| 273 | break; |
| 274 | case 0x080 >> 2: // OTG Control Status Register |
| 275 | write8(usb.regs.otgcsr, bit_offset, value & 0x1A00FFF7 >> bit_offset); // W mask (V) |
| 276 | break; |
| 277 | case 0x084 >> 2: // OTG Interrupt Status Register |
| 278 | usb.regs.otgisr &= ~((uint32_t)value << bit_offset & OTGISR_MASK); // WC mask (V) |
| 279 | break; |
| 280 | case 0x088 >> 2: // OTG Interrupt Enable Register |
| 281 | write8(usb.regs.otgier, bit_offset, value & OTGISR_MASK >> bit_offset); // W mask (V) |
| 282 | break; |
| 283 | case 0x0C0 >> 2: // Global Interrupt Status Register |
| 284 | usb.regs.isr &= ~((uint32_t)value << bit_offset & ISR_MASK); // WC mask (V) |
| 285 | break; |
| 286 | case 0x0C4 >> 2: // Global Interrupt Mask Register |
nothing calls this directly
no test coverage detected