1/*
2 * BK Id: SCCS/s.adb.c 1.5 05/17/01 18:14:23 cort
3 */
4/*
5 * Copyright (C) 1996 Paul Mackerras.
6 */
7#include "nonstdio.h"
8#include "privinst.h"
9
10#define scanhex	xmon_scanhex
11#define skipbl	xmon_skipbl
12
13#define ADB_B		(*(volatile unsigned char *)0xf3016000)
14#define ADB_SR		(*(volatile unsigned char *)0xf3017400)
15#define ADB_ACR		(*(volatile unsigned char *)0xf3017600)
16#define ADB_IFR		(*(volatile unsigned char *)0xf3017a00)
17
18static inline void eieio(void) { asm volatile ("eieio" : :); }
19
20#define N_ADB_LOG	1000
21struct adb_log {
22    unsigned char b;
23    unsigned char ifr;
24    unsigned char acr;
25    unsigned int time;
26} adb_log[N_ADB_LOG];
27int n_adb_log;
28
29void
30init_adb_log(void)
31{
32    adb_log[0].b = ADB_B;
33    adb_log[0].ifr = ADB_IFR;
34    adb_log[0].acr = ADB_ACR;
35    adb_log[0].time = get_dec();
36    n_adb_log = 0;
37}
38
39void
40dump_adb_log(void)
41{
42    unsigned t, t0;
43    struct adb_log *ap;
44    int i;
45
46    ap = adb_log;
47    t0 = ap->time;
48    for (i = 0; i <= n_adb_log; ++i, ++ap) {
49	t = t0 - ap->time;
50	printf("b=%x ifr=%x acr=%x at %d.%.7d\n", ap->b, ap->ifr, ap->acr,
51	       t / 1000000000, (t % 1000000000) / 100);
52    }
53}
54
55void
56adb_chklog(void)
57{
58    struct adb_log *ap = &adb_log[n_adb_log + 1];
59
60    ap->b = ADB_B;
61    ap->ifr = ADB_IFR;
62    ap->acr = ADB_ACR;
63    if (ap->b != ap[-1].b || (ap->ifr & 4) != (ap[-1].ifr & 4)
64	|| ap->acr != ap[-1].acr) {
65	ap->time = get_dec();
66	++n_adb_log;
67    }
68}
69
70int
71adb_bitwait(int bmask, int bval, int fmask, int fval)
72{
73    int i;
74    struct adb_log *ap;
75
76    for (i = 10000; i > 0; --i) {
77	adb_chklog();
78	ap = &adb_log[n_adb_log];
79	if ((ap->b & bmask) == bval && (ap->ifr & fmask) == fval)
80	    return 0;
81    }
82    return -1;
83}
84
85int
86adb_wait(void)
87{
88    if (adb_bitwait(0, 0, 4, 4) < 0) {
89	printf("adb: ready wait timeout\n");
90	return -1;
91    }
92    return 0;
93}
94
95void
96adb_readin(void)
97{
98    int i, j;
99    unsigned char d[64];
100
101    if (ADB_B & 8) {
102	printf("ADB_B: %x\n", ADB_B);
103	return;
104    }
105    i = 0;
106    adb_wait();
107    j = ADB_SR;
108    eieio();
109    ADB_B &= ~0x20;
110    eieio();
111    for (;;) {
112	if (adb_wait() < 0)
113	    break;
114	d[i++] = ADB_SR;
115	eieio();
116	if (ADB_B & 8)
117	    break;
118	ADB_B ^= 0x10;
119	eieio();
120    }
121    ADB_B |= 0x30;
122    if (adb_wait() == 0)
123	j = ADB_SR;
124    for (j = 0; j < i; ++j)
125	printf("%.2x ", d[j]);
126    printf("\n");
127}
128
129int
130adb_write(unsigned char *d, int i)
131{
132    int j;
133    unsigned x;
134
135    if ((ADB_B & 8) == 0) {
136	printf("r: ");
137	adb_readin();
138    }
139    for (;;) {
140	ADB_ACR = 0x1c;
141	eieio();
142	ADB_SR = d[0];
143	eieio();
144	ADB_B &= ~0x20;
145	eieio();
146	if (ADB_B & 8)
147	    break;
148	ADB_ACR = 0xc;
149	eieio();
150	ADB_B |= 0x20;
151	eieio();
152	adb_readin();
153    }
154    adb_wait();
155    for (j = 1; j < i; ++j) {
156	ADB_SR = d[j];
157	eieio();
158	ADB_B ^= 0x10;
159	eieio();
160	if (adb_wait() < 0)
161	    break;
162    }
163    ADB_ACR = 0xc;
164    eieio();
165    x = ADB_SR;
166    eieio();
167    ADB_B |= 0x30;
168    return j;
169}
170
171void
172adbcmds(void)
173{
174    char cmd;
175    unsigned rtcu, rtcl, dec, pdec, x;
176    int i, j;
177    unsigned char d[64];
178
179    cmd = skipbl();
180    switch (cmd) {
181    case 't':
182	for (;;) {
183	    rtcl = get_rtcl();
184	    rtcu = get_rtcu();
185	    dec = get_dec();
186	    printf("rtc u=%u l=%u dec=%x (%d = %d.%.7d)\n",
187		   rtcu, rtcl, dec, pdec - dec, (pdec - dec) / 1000000000,
188		   ((pdec - dec) % 1000000000) / 100);
189	    pdec = dec;
190	    if (cmd == 'x')
191		break;
192	    while (xmon_read(stdin, &cmd, 1) != 1)
193		;
194	}
195	break;
196    case 'r':
197	init_adb_log();
198	while (adb_bitwait(8, 0, 0, 0) == 0)
199	    adb_readin();
200	break;
201    case 'w':
202	i = 0;
203	while (scanhex(&x))
204	    d[i++] = x;
205	init_adb_log();
206	j = adb_write(d, i);
207	printf("sent %d bytes\n", j);
208	while (adb_bitwait(8, 0, 0, 0) == 0)
209	    adb_readin();
210	break;
211    case 'l':
212	dump_adb_log();
213	break;
214    }
215}
216