Add bwio
[arm/overo-bwio.git] / src / bwio.c
1 /*
2  * bwio.c - busy-wait I/O routines for diagnosis
3  *
4  * Specific to the TS-7200 ARM evaluation board
5  *
6  */
7
8 #include <ts7200.h>
9 #include <bwio.h>
10
11 /*
12  * The UARTs are initialized by RedBoot to the following state
13  *      115,200 bps
14  *      8 bits
15  *      no parity
16  *      fifos enabled
17  */
18 int bwsetfifo( int channel, int state ) {
19         int *line, buf;
20         switch( channel ) {
21         case COM1:
22                 line = (int *)( UART1_BASE + UART_LCRH_OFFSET );
23                 break;
24         case COM2:
25                 line = (int *)( UART2_BASE + UART_LCRH_OFFSET );
26                 break;
27         default:
28                 return -1;
29                 break;
30         }
31         buf = *line;
32         buf = state ? buf | FEN_MASK : buf & ~FEN_MASK;
33         *line = buf;
34         return 0;
35 }
36
37 int bwsetspeed( int channel, int speed ) {
38         int *high, *low;
39         switch( channel ) {
40         case COM1:
41                 high = (int *)( UART1_BASE + UART_LCRM_OFFSET );
42                 low = (int *)( UART1_BASE + UART_LCRL_OFFSET );
43                 break;
44         case COM2:
45                 high = (int *)( UART2_BASE + UART_LCRM_OFFSET );
46                 low = (int *)( UART2_BASE + UART_LCRL_OFFSET );
47                 break;
48         default:
49                 return -1;
50                 break;
51         }
52         switch( speed ) {
53         case 115200:
54                 *high = 0x0;
55                 *low = 0x3;
56                 return 0;
57         case 2400:
58                 *high = 0x0;
59                 *low = 0x90;
60                 return 0;
61         default:
62                 return -1;
63         }
64 }
65
66 int bwputc( int channel, char c ) {
67         int *flags, *data;
68         switch( channel ) {
69         case COM1:
70                 flags = (int *)( UART1_BASE + UART_FLAG_OFFSET );
71                 data = (int *)( UART1_BASE + UART_DATA_OFFSET );
72                 break;
73         case COM2:
74                 flags = (int *)( UART2_BASE + UART_FLAG_OFFSET );
75                 data = (int *)( UART2_BASE + UART_DATA_OFFSET );
76                 break;
77         default:
78                 return -1;
79                 break;
80         }
81         while( ( *flags & TXFF_MASK ) ) ;
82         *data = c;
83         return 0;
84 }
85
86 char c2x( char ch ) {
87         if ( (ch <= 9) ) return '0' + ch;
88         return 'a' + ch - 10;
89 }
90
91 int bwputx( int channel, char c ) {
92         char chh, chl;
93
94         chh = c2x( c / 16 );
95         chl = c2x( c % 16 );
96         bwputc( channel, chh );
97         return bwputc( channel, chl );
98 }
99
100 int bwputr( int channel, unsigned int reg ) {
101         int byte;
102         char *ch = (char *) &reg;
103
104         for( byte = 3; byte >= 0; byte-- ) bwputx( channel, ch[byte] );
105         return bwputc( channel, ' ' );
106 }
107
108 int bwputstr( int channel, char *str ) {
109         while( *str ) {
110                 if( bwputc( channel, *str ) < 0 ) return -1;
111                 str++;
112         }
113         return 0;
114 }
115
116 void bwputw( int channel, int n, char fc, char *bf ) {
117         char ch;
118         char *p = bf;
119
120         while( *p++ && n > 0 ) n--;
121         while( n-- > 0 ) bwputc( channel, fc );
122         while( ( ch = *bf++ ) ) bwputc( channel, ch );
123 }
124
125 int bwgetc( int channel ) {
126         int *flags, *data;
127         unsigned char c;
128
129         switch( channel ) {
130         case COM1:
131                 flags = (int *)( UART1_BASE + UART_FLAG_OFFSET );
132                 data = (int *)( UART1_BASE + UART_DATA_OFFSET );
133                 break;
134         case COM2:
135                 flags = (int *)( UART2_BASE + UART_FLAG_OFFSET );
136                 data = (int *)( UART2_BASE + UART_DATA_OFFSET );
137                 break;
138         default:
139                 return -1;
140                 break;
141         }
142         while ( !( *flags & RXFF_MASK ) ) ;
143         c = *data;
144         return c;
145 }
146
147 int bwa2d( char ch ) {
148         if( ch >= '0' && ch <= '9' ) return ch - '0';
149         if( ch >= 'a' && ch <= 'f' ) return ch - 'a' + 10;
150         if( ch >= 'A' && ch <= 'F' ) return ch - 'A' + 10;
151         return -1;
152 }
153
154 char bwa2i( char ch, char **src, int base, int *nump ) {
155         int num, digit;
156         char *p;
157
158         p = *src; num = 0;
159         while( ( digit = bwa2d( ch ) ) >= 0 ) {
160                 if ( digit > base ) break;
161                 num = num*base + digit;
162                 ch = *p++;
163         }
164         *src = p; *nump = num;
165         return ch;
166 }
167
168 void bwui2a( unsigned int num, unsigned int base, char *bf ) {
169         int n = 0;
170         int dgt;
171         unsigned int d = 1;
172         
173         while( (num / d) >= base ) d *= base;
174         while( d != 0 ) {
175                 dgt = num / d;
176                 num %= d;
177                 d /= base;
178                 if( n || dgt > 0 || d == 0 ) {
179                         *bf++ = dgt + ( dgt < 10 ? '0' : 'a' - 10 );
180                         ++n;
181                 }
182         }
183         *bf = 0;
184 }
185
186 void bwi2a( int num, char *bf ) {
187         if( num < 0 ) {
188                 num = -num;
189                 *bf++ = '-';
190         }
191         bwui2a( num, 10, bf );
192 }
193
194 void bwformat ( int channel, char *fmt, va_list va ) {
195         char bf[12];
196         char ch, lz;
197         int w;
198
199         
200         while ( ( ch = *(fmt++) ) ) {
201                 if ( ch != '%' )
202                         bwputc( channel, ch );
203                 else {
204                         lz = 0; w = 0;
205                         ch = *(fmt++);
206                         switch ( ch ) {
207                         case '0':
208                                 lz = 1; ch = *(fmt++);
209                                 break;
210                         case '1':
211                         case '2':
212                         case '3':
213                         case '4':
214                         case '5':
215                         case '6':
216                         case '7':
217                         case '8':
218                         case '9':
219                                 ch = bwa2i( ch, &fmt, 10, &w );
220                                 break;
221                         }
222                         switch( ch ) {
223                         case 0: return;
224                         case 'c':
225                                 bwputc( channel, va_arg( va, char ) );
226                                 break;
227                         case 's':
228                                 bwputw( channel, w, 0, va_arg( va, char* ) );
229                                 break;
230                         case 'u':
231                                 bwui2a( va_arg( va, unsigned int ), 10, bf );
232                                 bwputw( channel, w, lz, bf );
233                                 break;
234                         case 'd':
235                                 bwi2a( va_arg( va, int ), bf );
236                                 bwputw( channel, w, lz, bf );
237                                 break;
238                         case 'x':
239                                 bwui2a( va_arg( va, unsigned int ), 16, bf );
240                                 bwputw( channel, w, lz, bf );
241                                 break;
242                         case '%':
243                                 bwputc( channel, ch );
244                                 break;
245                         }
246                 }
247         }
248 }
249
250 void bwprintf( int channel, char *fmt, ... ) {
251         va_list va;
252
253         va_start(va,fmt);
254         bwformat( channel, fmt, va );
255         va_end(va);
256 }
257