25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_ns16550.c,v 1.40 2005/08/12 06:15:31 debug Exp $ |
* $Id: dev_ns16550.c,v 1.41 2005/09/30 13:33:01 debug Exp $ |
29 |
* |
* |
30 |
* NS16550 serial controller. |
* NS16550 serial controller. |
31 |
* |
* |
56 |
int addrmult; |
int addrmult; |
57 |
int in_use; |
int in_use; |
58 |
int irqnr; |
int irqnr; |
59 |
|
char *name; |
60 |
int console_handle; |
int console_handle; |
61 |
int enable_fifo; |
int enable_fifo; |
62 |
|
|
118 |
|
|
119 |
/* The NS16550 should be accessed using byte read/writes: */ |
/* The NS16550 should be accessed using byte read/writes: */ |
120 |
if (len != 1) |
if (len != 1) |
121 |
fatal("[ ns16550: len=%i, idata=0x%16llx! ]\n", |
fatal("[ ns16550 (%s): len=%i, idata=0x%16llx! ]\n", |
122 |
len, (long long)idata); |
d->name, len, (long long)idata); |
123 |
|
|
124 |
/* |
/* |
125 |
* Always ready to transmit: |
* Always ready to transmit: |
138 |
relative_addr /= d->addrmult; |
relative_addr /= d->addrmult; |
139 |
|
|
140 |
if (relative_addr >= DEV_NS16550_LENGTH) { |
if (relative_addr >= DEV_NS16550_LENGTH) { |
141 |
fatal("[ ns16550: outside register space? relative_addr=" |
fatal("[ ns16550 (%s): outside register space? relative_addr=" |
142 |
"0x%llx. bad addrmult? bad device length? ]\n", |
"0x%llx. bad addrmult? bad device length? ]\n", d->name, |
143 |
(long long)relative_addr); |
(long long)relative_addr); |
144 |
return 0; |
return 0; |
145 |
} |
} |
179 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
180 |
/* Set the high byte of the divisor: */ |
/* Set the high byte of the divisor: */ |
181 |
d->divisor = (d->divisor & 0xff) | (idata << 8); |
d->divisor = (d->divisor & 0xff) | (idata << 8); |
182 |
debug("[ ns16550: speed set to %i bps ]\n", |
debug("[ ns16550 (%s): speed set to %i bps ]\n", |
183 |
(int)(115200 / d->divisor)); |
d->name, (int)(115200 / d->divisor)); |
184 |
} else |
} else |
185 |
odata = d->divisor >> 8; |
odata = d->divisor >> 8; |
186 |
break; |
break; |
190 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
191 |
/* This is to supress Linux' behaviour */ |
/* This is to supress Linux' behaviour */ |
192 |
if (idata != 0) |
if (idata != 0) |
193 |
debug("[ ns16550: write to ier: 0x%02x ]\n", |
debug("[ ns16550 (%s): write to ier: 0x%02x ]" |
194 |
(int)idata); |
"\n", d->name, (int)idata); |
195 |
|
|
196 |
/* Needed for NetBSD 2.0.x, but not 1.6.2? */ |
/* Needed for NetBSD 2.0.x, but not 1.6.2? */ |
197 |
if (!(d->reg[com_ier] & IER_ETXRDY) |
if (!(d->reg[com_ier] & IER_ETXRDY) |
206 |
|
|
207 |
case com_iir: /* interrupt identification (r), fifo control (w) */ |
case com_iir: /* interrupt identification (r), fifo control (w) */ |
208 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
209 |
debug("[ ns16550: write to fifo control: 0x%02x ]\n", |
debug("[ ns16550 (%s): write to fifo control: 0x%02x ]" |
210 |
(int)idata); |
"\n", d->name, (int)idata); |
211 |
d->fcr = idata; |
d->fcr = idata; |
212 |
} else { |
} else { |
213 |
odata = d->reg[com_iir]; |
odata = d->reg[com_iir]; |
214 |
debug("[ ns16550: read from iir: 0x%02x ]\n", |
debug("[ ns16550 (%s): read from iir: 0x%02x ]\n", |
215 |
(int)odata); |
d->name, (int)odata); |
216 |
dev_ns16550_tick(cpu, d); |
dev_ns16550_tick(cpu, d); |
217 |
} |
} |
218 |
break; |
break; |
219 |
|
|
220 |
case com_lsr: |
case com_lsr: |
221 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
222 |
debug("[ ns16550: write to lsr: 0x%02x ]\n", |
debug("[ ns16550 (%s): write to lsr: 0x%02x ]\n", |
223 |
(int)idata); |
d->name, (int)idata); |
224 |
d->reg[com_lsr] = idata; |
d->reg[com_lsr] = idata; |
225 |
} else { |
} else { |
226 |
odata = d->reg[com_lsr]; |
odata = d->reg[com_lsr]; |
227 |
/* debug("[ ns16550: read from lsr: 0x%02x ]\n", |
/* debug("[ ns16550 (%s): read from lsr: 0x%02x ]\n", |
228 |
(int)odata); */ |
d->name, (int)odata); */ |
229 |
} |
} |
230 |
break; |
break; |
231 |
|
|
232 |
case com_msr: |
case com_msr: |
233 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
234 |
debug("[ ns16550: write to msr: 0x%02x ]\n", |
debug("[ ns16550 (%s): write to msr: 0x%02x ]\n", |
235 |
(int)idata); |
d->name, (int)idata); |
236 |
d->reg[com_msr] = idata; |
d->reg[com_msr] = idata; |
237 |
} else { |
} else { |
238 |
odata = d->reg[com_msr]; |
odata = d->reg[com_msr]; |
239 |
debug("[ ns16550: read from msr: 0x%02x ]\n", |
debug("[ ns16550 (%s): read from msr: 0x%02x ]\n", |
240 |
(int)odata); |
d->name, (int)odata); |
241 |
} |
} |
242 |
break; |
break; |
243 |
|
|
267 |
|
|
268 |
d->dlab = idata & 0x80? 1 : 0; |
d->dlab = idata & 0x80? 1 : 0; |
269 |
|
|
270 |
debug("[ ns16550: write to lctl: 0x%02x (%s%s" |
debug("[ ns16550 (%s): write to lctl: 0x%02x (%s%s" |
271 |
"setting mode %i%c%s) ]\n", |
"setting mode %i%c%s) ]\n", d->name, (int)idata, |
|
(int)idata, |
|
272 |
d->dlab? "Divisor Latch access, " : "", |
d->dlab? "Divisor Latch access, " : "", |
273 |
idata&0x40? "sending BREAK, " : "", |
idata&0x40? "sending BREAK, " : "", |
274 |
d->databits, d->parity, d->stopbits); |
d->databits, d->parity, d->stopbits); |
275 |
} else { |
} else { |
276 |
odata = d->reg[com_lctl]; |
odata = d->reg[com_lctl]; |
277 |
debug("[ ns16550: read from lctl: 0x%02x ]\n", |
debug("[ ns16550 (%s): read from lctl: 0x%02x ]\n", |
278 |
(int)odata); |
d->name, (int)odata); |
279 |
} |
} |
280 |
break; |
break; |
281 |
|
|
282 |
case com_mcr: |
case com_mcr: |
283 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
284 |
d->reg[com_mcr] = idata; |
d->reg[com_mcr] = idata; |
285 |
debug("[ ns16550: write to mcr: 0x%02x ]\n", |
debug("[ ns16550 (%s): write to mcr: 0x%02x ]\n", |
286 |
(int)idata); |
d->name, (int)idata); |
287 |
} else { |
} else { |
288 |
odata = d->reg[com_mcr]; |
odata = d->reg[com_mcr]; |
289 |
debug("[ ns16550: read from mcr: 0x%02x ]\n", |
debug("[ ns16550 (%s): read from mcr: 0x%02x ]\n", |
290 |
(int)odata); |
d->name, (int)odata); |
291 |
} |
} |
292 |
break; |
break; |
293 |
|
|
294 |
default: |
default: |
295 |
if (writeflag==MEM_READ) { |
if (writeflag==MEM_READ) { |
296 |
debug("[ ns16550: read from reg %i ]\n", |
debug("[ ns16550 (%s): read from reg %i ]\n", |
297 |
(int)relative_addr); |
d->name, (int)relative_addr); |
298 |
odata = d->reg[relative_addr]; |
odata = d->reg[relative_addr]; |
299 |
} else { |
} else { |
300 |
debug("[ ns16550: write to reg %i:", |
debug("[ ns16550 (%s): write to reg %i:", |
301 |
(int)relative_addr); |
d->name, (int)relative_addr); |
302 |
for (i=0; i<len; i++) |
for (i=0; i<len; i++) |
303 |
debug(" %02x", data[i]); |
debug(" %02x", data[i]); |
304 |
debug(" ]\n"); |
debug(" ]\n"); |
327 |
exit(1); |
exit(1); |
328 |
} |
} |
329 |
memset(d, 0, sizeof(struct ns_data)); |
memset(d, 0, sizeof(struct ns_data)); |
330 |
d->irqnr = devinit->irq_nr; |
d->irqnr = devinit->irq_nr; |
331 |
d->addrmult = devinit->addr_mult; |
d->addrmult = devinit->addr_mult; |
332 |
d->in_use = devinit->in_use; |
d->in_use = devinit->in_use; |
333 |
d->enable_fifo = 1; |
d->enable_fifo = 1; |
334 |
d->dlab = 0; |
d->dlab = 0; |
335 |
d->divisor = 115200 / 9600; |
d->divisor = 115200 / 9600; |
336 |
d->databits = 8; |
d->databits = 8; |
337 |
d->parity = 'N'; |
d->parity = 'N'; |
338 |
d->stopbits = "1"; |
d->stopbits = "1"; |
339 |
|
d->name = devinit->name2 != NULL? devinit->name2 : ""; |
340 |
d->console_handle = |
d->console_handle = |
341 |
console_start_slave(devinit->machine, devinit->name); |
console_start_slave(devinit->machine, devinit->name); |
342 |
|
|