1 /* Low-level parallel port routines for the Atari builtin port
2 *
3 * Author: Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
4 *
5 * Based on parport_amiga.c.
6 *
7 * The built-in Atari parallel port provides one port at a fixed address
8 * with 8 output data lines (D0 - D7), 1 output control line (STROBE)
9 * and 1 input status line (BUSY) able to cause an interrupt.
10 */
11
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/parport.h>
15 #include <asm/setup.h>
16 #include <asm/atarihw.h>
17 #include <asm/irq.h>
18 #include <asm/atariints.h>
19
20 static struct parport *this_port = NULL;
21
22 static unsigned char
parport_atari_read_data(struct parport * p)23 parport_atari_read_data(struct parport *p)
24 {
25 unsigned long flags;
26 unsigned char data;
27
28 save_flags(flags);
29 cli();
30 sound_ym.rd_data_reg_sel = 15;
31 data = sound_ym.rd_data_reg_sel;
32 restore_flags(flags);
33 return data;
34 }
35
36 static void
parport_atari_write_data(struct parport * p,unsigned char data)37 parport_atari_write_data(struct parport *p, unsigned char data)
38 {
39 unsigned long flags;
40
41 save_flags(flags);
42 cli();
43 sound_ym.rd_data_reg_sel = 15;
44 sound_ym.wd_data = data;
45 restore_flags(flags);
46 }
47
48 static unsigned char
parport_atari_read_control(struct parport * p)49 parport_atari_read_control(struct parport *p)
50 {
51 unsigned long flags;
52 unsigned char control = 0;
53
54 save_flags(flags);
55 cli();
56 sound_ym.rd_data_reg_sel = 14;
57 if (!(sound_ym.rd_data_reg_sel & (1 << 5)))
58 control = PARPORT_CONTROL_STROBE;
59 restore_flags(flags);
60 return control;
61 }
62
63 static void
parport_atari_write_control(struct parport * p,unsigned char control)64 parport_atari_write_control(struct parport *p, unsigned char control)
65 {
66 unsigned long flags;
67
68 save_flags(flags);
69 cli();
70 sound_ym.rd_data_reg_sel = 14;
71 if (control & PARPORT_CONTROL_STROBE)
72 sound_ym.wd_data = sound_ym.rd_data_reg_sel & ~(1 << 5);
73 else
74 sound_ym.wd_data = sound_ym.rd_data_reg_sel | (1 << 5);
75 restore_flags(flags);
76 }
77
78 static unsigned char
parport_atari_frob_control(struct parport * p,unsigned char mask,unsigned char val)79 parport_atari_frob_control(struct parport *p, unsigned char mask,
80 unsigned char val)
81 {
82 unsigned char old = parport_atari_read_control(p);
83 parport_atari_write_control(p, (old & ~mask) ^ val);
84 return old;
85 }
86
87 static unsigned char
parport_atari_read_status(struct parport * p)88 parport_atari_read_status(struct parport *p)
89 {
90 return ((mfp.par_dt_reg & 1 ? 0 : PARPORT_STATUS_BUSY) |
91 PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR);
92 }
93
94 static void
parport_atari_init_state(struct pardevice * d,struct parport_state * s)95 parport_atari_init_state(struct pardevice *d, struct parport_state *s)
96 {
97 }
98
99 static void
parport_atari_save_state(struct parport * p,struct parport_state * s)100 parport_atari_save_state(struct parport *p, struct parport_state *s)
101 {
102 }
103
104 static void
parport_atari_restore_state(struct parport * p,struct parport_state * s)105 parport_atari_restore_state(struct parport *p, struct parport_state *s)
106 {
107 }
108
109 static void
parport_atari_interrupt(int irq,void * dev_id,struct pt_regs * regs)110 parport_atari_interrupt(int irq, void *dev_id, struct pt_regs *regs)
111 {
112 parport_generic_irq(irq, (struct parport *) dev_id, regs);
113 }
114
115 static void
parport_atari_enable_irq(struct parport * p)116 parport_atari_enable_irq(struct parport *p)
117 {
118 enable_irq(IRQ_MFP_BUSY);
119 }
120
121 static void
parport_atari_disable_irq(struct parport * p)122 parport_atari_disable_irq(struct parport *p)
123 {
124 disable_irq(IRQ_MFP_BUSY);
125 }
126
127 static void
parport_atari_data_forward(struct parport * p)128 parport_atari_data_forward(struct parport *p)
129 {
130 unsigned long flags;
131
132 save_flags(flags);
133 cli();
134 /* Soundchip port B as output. */
135 sound_ym.rd_data_reg_sel = 7;
136 sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x40;
137 restore_flags(flags);
138 }
139
140 static void
parport_atari_data_reverse(struct parport * p)141 parport_atari_data_reverse(struct parport *p)
142 {
143 #if 0 /* too dangerous, can kill sound chip */
144 unsigned long flags;
145
146 save_flags(flags);
147 cli();
148 /* Soundchip port B as input. */
149 sound_ym.rd_data_reg_sel = 7;
150 sound_ym.wd_data = sound_ym.rd_data_reg_sel & ~0x40;
151 restore_flags(flags);
152 #endif
153 }
154
155 static void
parport_atari_inc_use_count(void)156 parport_atari_inc_use_count(void)
157 {
158 MOD_INC_USE_COUNT;
159 }
160
161 static void
parport_atari_dec_use_count(void)162 parport_atari_dec_use_count(void)
163 {
164 MOD_DEC_USE_COUNT;
165 }
166
167 static struct parport_operations parport_atari_ops = {
168 parport_atari_write_data,
169 parport_atari_read_data,
170
171 parport_atari_write_control,
172 parport_atari_read_control,
173 parport_atari_frob_control,
174
175 parport_atari_read_status,
176
177 parport_atari_enable_irq,
178 parport_atari_disable_irq,
179
180 parport_atari_data_forward,
181 parport_atari_data_reverse,
182
183 parport_atari_init_state,
184 parport_atari_save_state,
185 parport_atari_restore_state,
186
187 parport_atari_inc_use_count,
188 parport_atari_dec_use_count,
189
190 parport_ieee1284_epp_write_data,
191 parport_ieee1284_epp_read_data,
192 parport_ieee1284_epp_write_addr,
193 parport_ieee1284_epp_read_addr,
194
195 parport_ieee1284_ecp_write_data,
196 parport_ieee1284_ecp_read_data,
197 parport_ieee1284_ecp_write_addr,
198
199 parport_ieee1284_write_compat,
200 parport_ieee1284_read_nibble,
201 parport_ieee1284_read_byte,
202 };
203
204
205 int __init
parport_atari_init(void)206 parport_atari_init(void)
207 {
208 struct parport *p;
209 unsigned long flags;
210
211 if (MACH_IS_ATARI) {
212 save_flags(flags);
213 cli();
214 /* Soundchip port A/B as output. */
215 sound_ym.rd_data_reg_sel = 7;
216 sound_ym.wd_data = (sound_ym.rd_data_reg_sel & 0x3f) | 0xc0;
217 /* STROBE high. */
218 sound_ym.rd_data_reg_sel = 14;
219 sound_ym.wd_data = sound_ym.rd_data_reg_sel | (1 << 5);
220 restore_flags(flags);
221 /* MFP port I0 as input. */
222 mfp.data_dir &= ~1;
223 /* MFP port I0 interrupt on high->low edge. */
224 mfp.active_edge &= ~1;
225 p = parport_register_port((unsigned long)&sound_ym.wd_data,
226 IRQ_MFP_BUSY, PARPORT_DMA_NONE,
227 &parport_atari_ops);
228 if (!p)
229 return 0;
230 if (request_irq(IRQ_MFP_BUSY, parport_atari_interrupt,
231 IRQ_TYPE_SLOW, p->name, p)) {
232 parport_unregister_port (p);
233 return 0;
234 }
235
236 this_port = p;
237 printk(KERN_INFO "%s: Atari built-in port using irq\n", p->name);
238 parport_proc_register(p);
239
240 parport_announce_port (p);
241
242 return 1;
243 }
244 return 0;
245 }
246
247 #ifdef MODULE
248
249 MODULE_AUTHOR("Andreas Schwab");
250 MODULE_DESCRIPTION("Parport Driver for Atari builtin Port");
251 MODULE_SUPPORTED_DEVICE("Atari builtin Parallel Port");
252 MODULE_LICENSE("GPL");
253
254 int
init_module(void)255 init_module(void)
256 {
257 return parport_atari_init() ? 0 : -ENODEV;
258 }
259
260 void
cleanup_module(void)261 cleanup_module(void)
262 {
263 if (this_port->irq != PARPORT_IRQ_NONE)
264 free_irq(IRQ_MFP_BUSY, this_port);
265 parport_proc_unregister(this_port);
266 parport_unregister_port(this_port);
267 }
268 #endif
269