mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-31 12:05:05 +02:00
fix crash: 0x23CC50 is the RDP pointer, not a CSR0 shadow
The restore wrote 0x0042 into 0x23CC50, overwriting the driver's RDP pointer (0x05800000); the next CSR access then targeted 0x0042 and the terminal died with an illegal opcode. The TX kick does move @0x23CC50,a3 / move *a3,a5 -- it reads the live CSR0 and ORs TDMD, there is no shadow cell. Report: section 10 corrected, section 62 added with the disassembly and the consequence.
This commit is contained in:
1 parent
2ec9787435
commit
3cd03cdc19
5 files changed
+54
-8
No files matched your search
@@ -249,10 +249,21 @@ a5 |= 0x0008 ; TDMD
|
||||
> real-silicon `CSR0 = 0x1BB` decode (`STRT`=1, `TDMD`=1, `TXON`=1) shows a poll
|
||||
> that never ran, which is a different problem entirely.
|
||||
|
||||
**The transmit demand is sent as `shadow | TDMD`, never as a bare `TDMD`.** The
|
||||
write must preserve the shadow's read/write bits (in particular `INEA`), and it
|
||||
matches the driver; our payload arms the descriptor at kick time and writes
|
||||
`STRT|TDMD` in one word.
|
||||
**The transmit demand is sent as `CSR0-read-back | TDMD`.** `0x23CC50` is **not**
|
||||
a shadow cell — it holds the driver's **RDP pointer** (`0x05800000`), and the kick
|
||||
reads CSR0 back through it:
|
||||
|
||||
```
|
||||
3F9D5960 move @0x23CC50,a3,1 ; a3 = RDP pointer (0x05800000)
|
||||
3F9D5990 move *a3,a5,0 ; a5 = *RDP = current CSR0
|
||||
3F9D59B0 or a3=8,a5 ; a5 |= TDMD
|
||||
3F9D59D0 move @0x23CC30,a5,1 ; a5 = RDP pointer (second alias)
|
||||
3F9D5A00 move *a13,*a5,0 ; *RDP = a5
|
||||
```
|
||||
|
||||
So the driver reads the *live* CSR0 and ORs `TDMD`, preserving whatever
|
||||
read/write bits (notably `INEA`) are currently set. Section 10 called that cell a
|
||||
"shadow" and section 62 records why that is wrong and what it broke.
|
||||
|
||||
## 11. The live driver paths (RX poll, TX completion)
|
||||
|
||||
@@ -4225,3 +4236,34 @@ from the real unit (they are the ones that displayed correctly there). MAME's
|
||||
frame dump does **not** reproduce the panel — the OS repaints the screen
|
||||
continuously there, and the real unit's VRAM layout differs slightly — so the
|
||||
panel is verified on the machine, not from an emulator screenshot.
|
||||
|
||||
## 62. Correction: `0x23CC50` is the RDP pointer, not a CSR0 shadow
|
||||
|
||||
Section 10 (and the restore code written from it) treated cell `0x23CC50` as a
|
||||
software shadow of CSR0 and wrote `0x0042` into it. That is wrong and it
|
||||
**crashed the terminal with an illegal opcode** on the machine.
|
||||
|
||||
The disassembly is unambiguous:
|
||||
|
||||
```
|
||||
3F9D5960 move @0x23CC50,a3,1 ; a3 = value of the cell = 0x05800000
|
||||
3F9D5990 move *a3,a5,0 ; a5 = *(0x05800000) = *RDP = current CSR0
|
||||
3F9D59B0 or a3=8,a5 ; a5 |= TDMD
|
||||
3F9D59D0 move @0x23CC30,a5,1 ; a5 = second RDP alias (also 0x05800000)
|
||||
3F9D5A00 move *a13,*a5,0 ; *RDP = a5
|
||||
```
|
||||
|
||||
`0x23CC50` holds a **pointer** (`0x05800000`, matching the RAM dump in section 2),
|
||||
and the driver reads the *live* CSR0 through it before OR-ing `TDMD`. There is no
|
||||
shadow: the "preserved" bits are simply whatever the chip currently reports.
|
||||
|
||||
Consequences, all now fixed:
|
||||
|
||||
* writing `0x0042` into `0x23CC50` overwrites the RDP pointer, so the driver's
|
||||
next CSR access targets address `0x0042` — the fault observed on the unit;
|
||||
* the restore must write CSR0 through `RAP`/`RDP`, never through that cell;
|
||||
* section 10's phrase "CSR0 = shadow | TDMD" should read "CSR0 = read-back | TDMD".
|
||||
|
||||
The restore path in `harness/udpstream/lance.c` now re-programs the chip with
|
||||
`0x7F41` (the firmware's own init value: `INIT | INEA | all status bits`), polls
|
||||
`IDON`, writes `0x0042`, and leaves the driver's cells untouched.
|
||||
Binary file not shown.
Binary file not shown.
@@ -408,8 +408,10 @@ int main()
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* keep the driver's command shadow consistent with the chip */
|
||||
*(unsigned int *)0x23CC50 = 0x0042;
|
||||
/* NOTE: do not write 0x23CC50 -- it is the driver's RDP pointer
|
||||
* cell (0x05800000), not a CSR0 shadow. The TX kick reads CSR0
|
||||
* back through it and ORs TDMD; storing here corrupts the pointer
|
||||
* and the next CSR access faults (illegal opcode). */
|
||||
}
|
||||
cell(0x260, csr0res); /* CSR0 after the restore */
|
||||
cell(0x280, osblk); /* init block we handed back */
|
||||
|
||||
@@ -408,8 +408,10 @@ int main()
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* keep the driver's command shadow consistent with the chip */
|
||||
*(unsigned int *)0x23CC50 = 0x0042;
|
||||
/* NOTE: do not write 0x23CC50 -- it is the driver's RDP pointer
|
||||
* cell (0x05800000), not a CSR0 shadow. The TX kick reads CSR0
|
||||
* back through it and ORs TDMD; storing here corrupts the pointer
|
||||
* and the next CSR access faults (illegal opcode). */
|
||||
}
|
||||
cell(0x260, csr0res); /* CSR0 after the restore */
|
||||
cell(0x280, osblk); /* init block we handed back */
|
||||
|
||||
Reference in new issue
Block a user