1
2
/*
* QEMU Parallel PORT emulation
ths
authored
17 years ago
3
*
4
* Copyright ( c ) 2003 - 2005 Fabrice Bellard
ths
authored
18 years ago
5
* Copyright ( c ) 2007 Marko Kohtala
ths
authored
17 years ago
6
*
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the "Software" ), to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
25
26
27
28
# include "hw.h"
# include "qemu-char.h"
# include "isa.h"
# include "pc.h"
29
30
31
// # define DEBUG_PARALLEL
ths
authored
18 years ago
32
33
34
35
36
37
38
39
40
41
42
43
# ifdef DEBUG_PARALLEL
# define pdebug ( fmt , arg ...) printf ( "pp: " fmt , ## arg )
# else
# define pdebug ( fmt , arg ...) (( void ) 0 )
# endif
# define PARA_REG_DATA 0
# define PARA_REG_STS 1
# define PARA_REG_CTR 2
# define PARA_REG_EPP_ADDR 3
# define PARA_REG_EPP_DATA 4
44
45
46
47
48
49
50
51
/*
* These are the definitions for the Printer Status Register
*/
# define PARA_STS_BUSY 0x80 /* Busy complement */
# define PARA_STS_ACK 0x40 /* Acknowledge */
# define PARA_STS_PAPER 0x20 /* Out of paper */
# define PARA_STS_ONLINE 0x10 /* Online */
# define PARA_STS_ERROR 0x08 /* Error complement */
ths
authored
18 years ago
52
# define PARA_STS_TMOUT 0x01 /* EPP timeout */
53
54
55
56
/*
* These are the definitions for the Printer Control Register
*/
ths
authored
18 years ago
57
# define PARA_CTR_DIR 0x20 /* Direction (1=read, 0=write) */
58
59
60
61
62
63
# define PARA_CTR_INTEN 0x10 /* IRQ Enable */
# define PARA_CTR_SELECT 0x08 /* Select In complement */
# define PARA_CTR_INIT 0x04 /* Initialize Printer complement */
# define PARA_CTR_AUTOLF 0x02 /* Auto linefeed complement */
# define PARA_CTR_STROBE 0x01 /* Strobe complement */
ths
authored
18 years ago
64
65
# define PARA_CTR_SIGNAL ( PARA_CTR_SELECT | PARA_CTR_INIT | PARA_CTR_AUTOLF | PARA_CTR_STROBE )
66
struct ParallelState {
ths
authored
18 years ago
67
68
69
uint8_t dataw ;
uint8_t datar ;
uint8_t status ;
70
uint8_t control ;
71
qemu_irq irq ;
72
73
int irq_pending ;
CharDriverState * chr ;
74
int hw_driver ;
ths
authored
18 years ago
75
76
int epp_timeout ;
uint32_t last_read_offset ; /* For debugging */
ths
authored
18 years ago
77
78
/* Memory-mapped interface */
int it_shift ;
79
80
81
82
83
};
static void parallel_update_irq ( ParallelState * s )
{
if ( s -> irq_pending )
84
qemu_irq_raise ( s -> irq );
85
else
86
qemu_irq_lower ( s -> irq );
87
88
}
ths
authored
18 years ago
89
90
static void
parallel_ioport_write_sw ( void * opaque , uint32_t addr , uint32_t val )
91
92
{
ParallelState * s = opaque ;
ths
authored
17 years ago
93
ths
authored
18 years ago
94
95
96
97
98
pdebug ( "write addr=0x%02x val=0x%02x \n " , addr , val );
addr &= 7 ;
switch ( addr ) {
case PARA_REG_DATA :
ths
authored
18 years ago
99
100
s -> dataw = val ;
parallel_update_irq ( s );
ths
authored
18 years ago
101
102
break ;
case PARA_REG_CTR :
103
val |= 0xc0 ;
ths
authored
18 years ago
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
if (( val & PARA_CTR_INIT ) == 0 ) {
s -> status = PARA_STS_BUSY ;
s -> status |= PARA_STS_ACK ;
s -> status |= PARA_STS_ONLINE ;
s -> status |= PARA_STS_ERROR ;
}
else if ( val & PARA_CTR_SELECT ) {
if ( val & PARA_CTR_STROBE ) {
s -> status &= ~ PARA_STS_BUSY ;
if (( s -> control & PARA_CTR_STROBE ) == 0 )
qemu_chr_write ( s -> chr , & s -> dataw , 1 );
} else {
if ( s -> control & PARA_CTR_INTEN ) {
s -> irq_pending = 1 ;
}
}
}
parallel_update_irq ( s );
s -> control = val ;
ths
authored
18 years ago
123
124
125
126
127
128
129
130
break ;
}
}
static void parallel_ioport_write_hw ( void * opaque , uint32_t addr , uint32_t val )
{
ParallelState * s = opaque ;
uint8_t parm = val ;
131
int dir ;
ths
authored
18 years ago
132
133
134
135
136
137
/* Sometimes programs do several writes for timing purposes on old
HW . Take care not to waste time on writes that do nothing . */
s -> last_read_offset = ~ 0U ;
138
139
addr &= 7 ;
switch ( addr ) {
ths
authored
18 years ago
140
141
case PARA_REG_DATA :
if ( s -> dataw == val )
ths
authored
18 years ago
142
143
144
145
return ;
pdebug ( "wd%02x \n " , val );
qemu_chr_ioctl ( s -> chr , CHR_IOCTL_PP_WRITE_DATA , & parm );
s -> dataw = val ;
146
break ;
ths
authored
18 years ago
147
case PARA_REG_STS :
ths
authored
18 years ago
148
149
150
151
pdebug ( "ws%02x \n " , val );
if ( val & PARA_STS_TMOUT )
s -> epp_timeout = 0 ;
break ;
ths
authored
18 years ago
152
153
154
case PARA_REG_CTR :
val |= 0xc0 ;
if ( s -> control == val )
ths
authored
18 years ago
155
156
return ;
pdebug ( "wc%02x \n " , val );
157
158
159
160
161
162
163
164
165
166
167
if (( val & PARA_CTR_DIR ) != ( s -> control & PARA_CTR_DIR )) {
if ( val & PARA_CTR_DIR ) {
dir = 1 ;
} else {
dir = 0 ;
}
qemu_chr_ioctl ( s -> chr , CHR_IOCTL_PP_DATA_DIR , & dir );
parm &= ~ PARA_CTR_DIR ;
}
ths
authored
18 years ago
168
169
qemu_chr_ioctl ( s -> chr , CHR_IOCTL_PP_WRITE_CONTROL , & parm );
s -> control = val ;
170
break ;
ths
authored
18 years ago
171
case PARA_REG_EPP_ADDR :
ths
authored
18 years ago
172
173
174
175
176
177
178
179
180
181
182
183
184
if (( s -> control & ( PARA_CTR_DIR | PARA_CTR_SIGNAL )) != PARA_CTR_INIT )
/* Controls not correct for EPP address cycle, so do nothing */
pdebug ( "wa%02x s \n " , val );
else {
struct ParallelIOArg ioarg = { . buffer = & parm , . count = 1 };
if ( qemu_chr_ioctl ( s -> chr , CHR_IOCTL_PP_EPP_WRITE_ADDR , & ioarg )) {
s -> epp_timeout = 1 ;
pdebug ( "wa%02x t \n " , val );
}
else
pdebug ( "wa%02x \n " , val );
}
break ;
ths
authored
18 years ago
185
case PARA_REG_EPP_DATA :
ths
authored
18 years ago
186
187
188
189
190
191
192
193
194
195
196
197
198
if (( s -> control & ( PARA_CTR_DIR | PARA_CTR_SIGNAL )) != PARA_CTR_INIT )
/* Controls not correct for EPP data cycle, so do nothing */
pdebug ( "we%02x s \n " , val );
else {
struct ParallelIOArg ioarg = { . buffer = & parm , . count = 1 };
if ( qemu_chr_ioctl ( s -> chr , CHR_IOCTL_PP_EPP_WRITE , & ioarg )) {
s -> epp_timeout = 1 ;
pdebug ( "we%02x t \n " , val );
}
else
pdebug ( "we%02x \n " , val );
}
break ;
ths
authored
18 years ago
199
200
201
202
203
204
205
206
207
208
}
}
static void
parallel_ioport_eppdata_write_hw2 ( void * opaque , uint32_t addr , uint32_t val )
{
ParallelState * s = opaque ;
uint16_t eppdata = cpu_to_le16 ( val );
int err ;
struct ParallelIOArg ioarg = {
ths
authored
18 years ago
209
. buffer = & eppdata , . count = sizeof ( eppdata )
ths
authored
18 years ago
210
211
};
if (( s -> control & ( PARA_CTR_DIR | PARA_CTR_SIGNAL )) != PARA_CTR_INIT ) {
ths
authored
18 years ago
212
213
214
/* Controls not correct for EPP data cycle, so do nothing */
pdebug ( "we%04x s \n " , val );
return ;
ths
authored
18 years ago
215
216
217
}
err = qemu_chr_ioctl ( s -> chr , CHR_IOCTL_PP_EPP_WRITE , & ioarg );
if ( err ) {
ths
authored
18 years ago
218
219
s -> epp_timeout = 1 ;
pdebug ( "we%04x t \n " , val );
ths
authored
18 years ago
220
221
}
else
ths
authored
18 years ago
222
pdebug ( "we%04x \n " , val );
ths
authored
18 years ago
223
224
225
226
227
228
229
230
231
}
static void
parallel_ioport_eppdata_write_hw4 ( void * opaque , uint32_t addr , uint32_t val )
{
ParallelState * s = opaque ;
uint32_t eppdata = cpu_to_le32 ( val );
int err ;
struct ParallelIOArg ioarg = {
ths
authored
18 years ago
232
. buffer = & eppdata , . count = sizeof ( eppdata )
ths
authored
18 years ago
233
234
};
if (( s -> control & ( PARA_CTR_DIR | PARA_CTR_SIGNAL )) != PARA_CTR_INIT ) {
ths
authored
18 years ago
235
236
237
/* Controls not correct for EPP data cycle, so do nothing */
pdebug ( "we%08x s \n " , val );
return ;
ths
authored
18 years ago
238
239
240
}
err = qemu_chr_ioctl ( s -> chr , CHR_IOCTL_PP_EPP_WRITE , & ioarg );
if ( err ) {
ths
authored
18 years ago
241
242
s -> epp_timeout = 1 ;
pdebug ( "we%08x t \n " , val );
243
}
ths
authored
18 years ago
244
else
ths
authored
18 years ago
245
pdebug ( "we%08x \n " , val );
246
247
}
ths
authored
18 years ago
248
static uint32_t parallel_ioport_read_sw ( void * opaque , uint32_t addr )
249
250
251
252
253
254
{
ParallelState * s = opaque ;
uint32_t ret = 0xff ;
addr &= 7 ;
switch ( addr ) {
ths
authored
18 years ago
255
case PARA_REG_DATA :
ths
authored
18 years ago
256
257
258
259
if ( s -> control & PARA_CTR_DIR )
ret = s -> datar ;
else
ret = s -> dataw ;
260
break ;
ths
authored
18 years ago
261
case PARA_REG_STS :
ths
authored
18 years ago
262
263
264
265
266
267
268
269
270
271
272
273
274
ret = s -> status ;
s -> irq_pending = 0 ;
if (( s -> status & PARA_STS_BUSY ) == 0 && ( s -> control & PARA_CTR_STROBE ) == 0 ) {
/* XXX Fixme: wait 5 microseconds */
if ( s -> status & PARA_STS_ACK )
s -> status &= ~ PARA_STS_ACK ;
else {
/* XXX Fixme: wait 5 microseconds */
s -> status |= PARA_STS_ACK ;
s -> status |= PARA_STS_BUSY ;
}
}
parallel_update_irq ( s );
275
break ;
ths
authored
18 years ago
276
case PARA_REG_CTR :
277
278
279
ret = s -> control ;
break ;
}
ths
authored
18 years ago
280
281
282
283
284
285
286
287
288
289
290
pdebug ( "read addr=0x%02x val=0x%02x \n " , addr , ret );
return ret ;
}
static uint32_t parallel_ioport_read_hw ( void * opaque , uint32_t addr )
{
ParallelState * s = opaque ;
uint8_t ret = 0xff ;
addr &= 7 ;
switch ( addr ) {
case PARA_REG_DATA :
ths
authored
18 years ago
291
292
293
qemu_chr_ioctl ( s -> chr , CHR_IOCTL_PP_READ_DATA , & ret );
if ( s -> last_read_offset != addr || s -> datar != ret )
pdebug ( "rd%02x \n " , ret );
ths
authored
18 years ago
294
295
296
s -> datar = ret ;
break ;
case PARA_REG_STS :
ths
authored
18 years ago
297
298
299
300
301
302
303
qemu_chr_ioctl ( s -> chr , CHR_IOCTL_PP_READ_STATUS , & ret );
ret &= ~ PARA_STS_TMOUT ;
if ( s -> epp_timeout )
ret |= PARA_STS_TMOUT ;
if ( s -> last_read_offset != addr || s -> status != ret )
pdebug ( "rs%02x \n " , ret );
s -> status = ret ;
ths
authored
18 years ago
304
305
306
break ;
case PARA_REG_CTR :
/* s -> control has some bits fixed to 1 . It is zero only when
ths
authored
18 years ago
307
308
309
310
311
312
313
314
315
316
317
318
it has not been yet written to . */
if ( s -> control == 0 ) {
qemu_chr_ioctl ( s -> chr , CHR_IOCTL_PP_READ_CONTROL , & ret );
if ( s -> last_read_offset != addr )
pdebug ( "rc%02x \n " , ret );
s -> control = ret ;
}
else {
ret = s -> control ;
if ( s -> last_read_offset != addr )
pdebug ( "rc%02x \n " , ret );
}
ths
authored
18 years ago
319
320
break ;
case PARA_REG_EPP_ADDR :
ths
authored
18 years ago
321
322
323
324
325
326
327
328
329
330
331
332
333
if (( s -> control & ( PARA_CTR_DIR | PARA_CTR_SIGNAL )) != ( PARA_CTR_DIR | PARA_CTR_INIT ))
/* Controls not correct for EPP addr cycle, so do nothing */
pdebug ( "ra%02x s \n " , ret );
else {
struct ParallelIOArg ioarg = { . buffer = & ret , . count = 1 };
if ( qemu_chr_ioctl ( s -> chr , CHR_IOCTL_PP_EPP_READ_ADDR , & ioarg )) {
s -> epp_timeout = 1 ;
pdebug ( "ra%02x t \n " , ret );
}
else
pdebug ( "ra%02x \n " , ret );
}
break ;
ths
authored
18 years ago
334
case PARA_REG_EPP_DATA :
ths
authored
18 years ago
335
336
337
338
339
340
341
342
343
344
345
346
347
if (( s -> control & ( PARA_CTR_DIR | PARA_CTR_SIGNAL )) != ( PARA_CTR_DIR | PARA_CTR_INIT ))
/* Controls not correct for EPP data cycle, so do nothing */
pdebug ( "re%02x s \n " , ret );
else {
struct ParallelIOArg ioarg = { . buffer = & ret , . count = 1 };
if ( qemu_chr_ioctl ( s -> chr , CHR_IOCTL_PP_EPP_READ , & ioarg )) {
s -> epp_timeout = 1 ;
pdebug ( "re%02x t \n " , ret );
}
else
pdebug ( "re%02x \n " , ret );
}
break ;
ths
authored
18 years ago
348
349
350
351
352
353
354
355
356
357
358
359
360
}
s -> last_read_offset = addr ;
return ret ;
}
static uint32_t
parallel_ioport_eppdata_read_hw2 ( void * opaque , uint32_t addr )
{
ParallelState * s = opaque ;
uint32_t ret ;
uint16_t eppdata = ~ 0 ;
int err ;
struct ParallelIOArg ioarg = {
ths
authored
18 years ago
361
. buffer = & eppdata , . count = sizeof ( eppdata )
ths
authored
18 years ago
362
363
};
if (( s -> control & ( PARA_CTR_DIR | PARA_CTR_SIGNAL )) != ( PARA_CTR_DIR | PARA_CTR_INIT )) {
ths
authored
18 years ago
364
365
366
/* Controls not correct for EPP data cycle, so do nothing */
pdebug ( "re%04x s \n " , eppdata );
return eppdata ;
ths
authored
18 years ago
367
368
369
370
371
}
err = qemu_chr_ioctl ( s -> chr , CHR_IOCTL_PP_EPP_READ , & ioarg );
ret = le16_to_cpu ( eppdata );
if ( err ) {
ths
authored
18 years ago
372
373
s -> epp_timeout = 1 ;
pdebug ( "re%04x t \n " , ret );
ths
authored
18 years ago
374
375
}
else
ths
authored
18 years ago
376
pdebug ( "re%04x \n " , ret );
ths
authored
18 years ago
377
378
379
380
381
382
383
384
385
386
387
return ret ;
}
static uint32_t
parallel_ioport_eppdata_read_hw4 ( void * opaque , uint32_t addr )
{
ParallelState * s = opaque ;
uint32_t ret ;
uint32_t eppdata = ~ 0U ;
int err ;
struct ParallelIOArg ioarg = {
ths
authored
18 years ago
388
. buffer = & eppdata , . count = sizeof ( eppdata )
ths
authored
18 years ago
389
390
};
if (( s -> control & ( PARA_CTR_DIR | PARA_CTR_SIGNAL )) != ( PARA_CTR_DIR | PARA_CTR_INIT )) {
ths
authored
18 years ago
391
392
393
/* Controls not correct for EPP data cycle, so do nothing */
pdebug ( "re%08x s \n " , eppdata );
return eppdata ;
ths
authored
18 years ago
394
395
396
397
398
}
err = qemu_chr_ioctl ( s -> chr , CHR_IOCTL_PP_EPP_READ , & ioarg );
ret = le32_to_cpu ( eppdata );
if ( err ) {
ths
authored
18 years ago
399
400
s -> epp_timeout = 1 ;
pdebug ( "re%08x t \n " , ret );
ths
authored
18 years ago
401
402
}
else
ths
authored
18 years ago
403
pdebug ( "re%08x \n " , ret );
ths
authored
18 years ago
404
405
406
407
408
409
410
411
412
413
414
415
416
417
return ret ;
}
static void parallel_ioport_ecp_write ( void * opaque , uint32_t addr , uint32_t val )
{
addr &= 7 ;
pdebug ( "wecp%d=%02x \n " , addr , val );
}
static uint32_t parallel_ioport_ecp_read ( void * opaque , uint32_t addr )
{
uint8_t ret = 0xff ;
addr &= 7 ;
pdebug ( "recp%d:%02x \n " , addr , ret );
418
419
420
return ret ;
}
421
static void parallel_reset ( void * opaque )
422
{
423
424
ParallelState * s = opaque ;
ths
authored
18 years ago
425
426
s -> datar = ~ 0 ;
s -> dataw = ~ 0 ;
427
428
429
430
s -> status = PARA_STS_BUSY ;
s -> status |= PARA_STS_ACK ;
s -> status |= PARA_STS_ONLINE ;
s -> status |= PARA_STS_ERROR ;
431
s -> status |= PARA_STS_TMOUT ;
432
433
s -> control = PARA_CTR_SELECT ;
s -> control |= PARA_CTR_INIT ;
434
s -> control |= 0xc0 ;
ths
authored
18 years ago
435
436
437
438
s -> irq_pending = 0 ;
s -> hw_driver = 0 ;
s -> epp_timeout = 0 ;
s -> last_read_offset = ~ 0U ;
ths
authored
18 years ago
439
440
441
442
443
444
445
446
447
}
/* If fd is zero, it means that the parallel device uses the console */
ParallelState * parallel_init ( int base , qemu_irq irq , CharDriverState * chr )
{
ParallelState * s ;
uint8_t dummy ;
s = qemu_mallocz ( sizeof ( ParallelState ));
448
449
450
451
s -> irq = irq ;
s -> chr = chr ;
parallel_reset ( s );
qemu_register_reset ( parallel_reset , s );
452
ths
authored
18 years ago
453
454
if ( qemu_chr_ioctl ( chr , CHR_IOCTL_PP_READ_STATUS , & dummy ) == 0 ) {
s -> hw_driver = 1 ;
ths
authored
18 years ago
455
s -> status = dummy ;
ths
authored
18 years ago
456
457
458
}
if ( s -> hw_driver ) {
ths
authored
18 years ago
459
460
461
462
463
464
465
466
register_ioport_write ( base , 8 , 1 , parallel_ioport_write_hw , s );
register_ioport_read ( base , 8 , 1 , parallel_ioport_read_hw , s );
register_ioport_write ( base + 4 , 1 , 2 , parallel_ioport_eppdata_write_hw2 , s );
register_ioport_read ( base + 4 , 1 , 2 , parallel_ioport_eppdata_read_hw2 , s );
register_ioport_write ( base + 4 , 1 , 4 , parallel_ioport_eppdata_write_hw4 , s );
register_ioport_read ( base + 4 , 1 , 4 , parallel_ioport_eppdata_read_hw4 , s );
register_ioport_write ( base + 0x400 , 8 , 1 , parallel_ioport_ecp_write , s );
register_ioport_read ( base + 0x400 , 8 , 1 , parallel_ioport_ecp_read , s );
ths
authored
18 years ago
467
468
}
else {
ths
authored
18 years ago
469
470
register_ioport_write ( base , 8 , 1 , parallel_ioport_write_sw , s );
register_ioport_read ( base , 8 , 1 , parallel_ioport_read_sw , s );
ths
authored
18 years ago
471
}
472
473
return s ;
}
ths
authored
18 years ago
474
475
/* Memory mapped interface */
476
static uint32_t parallel_mm_readb ( void * opaque , target_phys_addr_t addr )
ths
authored
18 years ago
477
478
479
{
ParallelState * s = opaque ;
480
return parallel_ioport_read_sw ( s , addr >> s -> it_shift ) & 0xFF ;
ths
authored
18 years ago
481
482
}
483
484
static void parallel_mm_writeb ( void * opaque ,
target_phys_addr_t addr , uint32_t value )
ths
authored
18 years ago
485
486
487
{
ParallelState * s = opaque ;
488
parallel_ioport_write_sw ( s , addr >> s -> it_shift , value & 0xFF );
ths
authored
18 years ago
489
490
}
491
static uint32_t parallel_mm_readw ( void * opaque , target_phys_addr_t addr )
ths
authored
18 years ago
492
493
494
{
ParallelState * s = opaque ;
495
return parallel_ioport_read_sw ( s , addr >> s -> it_shift ) & 0xFFFF ;
ths
authored
18 years ago
496
497
}
498
499
static void parallel_mm_writew ( void * opaque ,
target_phys_addr_t addr , uint32_t value )
ths
authored
18 years ago
500
501
502
{
ParallelState * s = opaque ;
503
parallel_ioport_write_sw ( s , addr >> s -> it_shift , value & 0xFFFF );
ths
authored
18 years ago
504
505
}
506
static uint32_t parallel_mm_readl ( void * opaque , target_phys_addr_t addr )
ths
authored
18 years ago
507
508
509
{
ParallelState * s = opaque ;
510
return parallel_ioport_read_sw ( s , addr >> s -> it_shift );
ths
authored
18 years ago
511
512
}
513
514
static void parallel_mm_writel ( void * opaque ,
target_phys_addr_t addr , uint32_t value )
ths
authored
18 years ago
515
516
517
{
ParallelState * s = opaque ;
518
parallel_ioport_write_sw ( s , addr >> s -> it_shift , value );
ths
authored
18 years ago
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
}
static CPUReadMemoryFunc * parallel_mm_read_sw [] = {
& parallel_mm_readb ,
& parallel_mm_readw ,
& parallel_mm_readl ,
};
static CPUWriteMemoryFunc * parallel_mm_write_sw [] = {
& parallel_mm_writeb ,
& parallel_mm_writew ,
& parallel_mm_writel ,
};
/* If fd is zero, it means that the parallel device uses the console */
ParallelState * parallel_mm_init ( target_phys_addr_t base , int it_shift , qemu_irq irq , CharDriverState * chr )
{
ParallelState * s ;
int io_sw ;
s = qemu_mallocz ( sizeof ( ParallelState ));
540
541
s -> irq = irq ;
s -> chr = chr ;
ths
authored
18 years ago
542
s -> it_shift = it_shift ;
543
544
parallel_reset ( s );
qemu_register_reset ( parallel_reset , s );
ths
authored
18 years ago
545
546
547
548
549
io_sw = cpu_register_io_memory ( 0 , parallel_mm_read_sw , parallel_mm_write_sw , s );
cpu_register_physical_memory ( base , 8 << it_shift , io_sw );
return s ;
}