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 <linux/interrupt.h> 16#include <asm/setup.h> 17#include <asm/atarihw.h> 18#include <asm/irq.h> 19#include <asm/atariints.h> 20 21static struct parport *this_port = NULL; 22 23static unsigned char 24parport_atari_read_data(struct parport *p) 25{ 26 unsigned long flags; 27 unsigned char data; 28 29 local_irq_save(flags); 30 sound_ym.rd_data_reg_sel = 15; 31 data = sound_ym.rd_data_reg_sel; 32 local_irq_restore(flags); 33 return data; 34} 35 36static void 37parport_atari_write_data(struct parport *p, unsigned char data) 38{ 39 unsigned long flags; 40 41 local_irq_save(flags); 42 sound_ym.rd_data_reg_sel = 15; 43 sound_ym.wd_data = data; 44 local_irq_restore(flags); 45} 46 47static unsigned char 48parport_atari_read_control(struct parport *p) 49{ 50 unsigned long flags; 51 unsigned char control = 0; 52 53 local_irq_save(flags); 54 sound_ym.rd_data_reg_sel = 14; 55 if (!(sound_ym.rd_data_reg_sel & (1 << 5))) 56 control = PARPORT_CONTROL_STROBE; 57 local_irq_restore(flags); 58 return control; 59} 60 61static void 62parport_atari_write_control(struct parport *p, unsigned char control) 63{ 64 unsigned long flags; 65 66 local_irq_save(flags); 67 sound_ym.rd_data_reg_sel = 14; 68 if (control & PARPORT_CONTROL_STROBE) 69 sound_ym.wd_data = sound_ym.rd_data_reg_sel & ~(1 << 5); 70 else 71 sound_ym.wd_data = sound_ym.rd_data_reg_sel | (1 << 5); 72 local_irq_restore(flags); 73} 74 75static unsigned char 76parport_atari_frob_control(struct parport *p, unsigned char mask, 77 unsigned char val) 78{ 79 unsigned char old = parport_atari_read_control(p); 80 parport_atari_write_control(p, (old & ~mask) ^ val); 81 return old; 82} 83 84static unsigned char 85parport_atari_read_status(struct parport *p) 86{ 87 return ((mfp.par_dt_reg & 1 ? 0 : PARPORT_STATUS_BUSY) | 88 PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR); 89} 90 91static void 92parport_atari_init_state(struct pardevice *d, struct parport_state *s) 93{ 94} 95 96static void 97parport_atari_save_state(struct parport *p, struct parport_state *s) 98{ 99} 100 101static void 102parport_atari_restore_state(struct parport *p, struct parport_state *s) 103{ 104} 105 106static irqreturn_t 107parport_atari_interrupt(int irq, void *dev_id) 108{ 109 parport_generic_irq(irq, (struct parport *) dev_id); 110 return IRQ_HANDLED; 111} 112 113static void 114parport_atari_enable_irq(struct parport *p) 115{ 116 enable_irq(IRQ_MFP_BUSY); 117} 118 119static void 120parport_atari_disable_irq(struct parport *p) 121{ 122 disable_irq(IRQ_MFP_BUSY); 123} 124 125static void 126parport_atari_data_forward(struct parport *p) 127{ 128 unsigned long flags; 129 130 local_irq_save(flags); 131 /* Soundchip port B as output. */ 132 sound_ym.rd_data_reg_sel = 7; 133 sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x40; 134 local_irq_restore(flags); 135} 136 137static void 138parport_atari_data_reverse(struct parport *p) 139{ 140} 141 142static struct parport_operations parport_atari_ops = { 143 .write_data = parport_atari_write_data, 144 .read_data = parport_atari_read_data, 145 146 .write_control = parport_atari_write_control, 147 .read_control = parport_atari_read_control, 148 .frob_control = parport_atari_frob_control, 149 150 .read_status = parport_atari_read_status, 151 152 .enable_irq = parport_atari_enable_irq, 153 .disable_irq = parport_atari_disable_irq, 154 155 .data_forward = parport_atari_data_forward, 156 .data_reverse = parport_atari_data_reverse, 157 158 .init_state = parport_atari_init_state, 159 .save_state = parport_atari_save_state, 160 .restore_state = parport_atari_restore_state, 161 162 .epp_write_data = parport_ieee1284_epp_write_data, 163 .epp_read_data = parport_ieee1284_epp_read_data, 164 .epp_write_addr = parport_ieee1284_epp_write_addr, 165 .epp_read_addr = parport_ieee1284_epp_read_addr, 166 167 .ecp_write_data = parport_ieee1284_ecp_write_data, 168 .ecp_read_data = parport_ieee1284_ecp_read_data, 169 .ecp_write_addr = parport_ieee1284_ecp_write_addr, 170 171 .compat_write_data = parport_ieee1284_write_compat, 172 .nibble_read_data = parport_ieee1284_read_nibble, 173 .byte_read_data = parport_ieee1284_read_byte, 174 175 .owner = THIS_MODULE, 176}; 177 178 179static int __init parport_atari_init(void) 180{ 181 struct parport *p; 182 unsigned long flags; 183 184 if (MACH_IS_ATARI) { 185 local_irq_save(flags); 186 /* Soundchip port A/B as output. */ 187 sound_ym.rd_data_reg_sel = 7; 188 sound_ym.wd_data = (sound_ym.rd_data_reg_sel & 0x3f) | 0xc0; 189 /* STROBE high. */ 190 sound_ym.rd_data_reg_sel = 14; 191 sound_ym.wd_data = sound_ym.rd_data_reg_sel | (1 << 5); 192 local_irq_restore(flags); 193 /* MFP port I0 as input. */ 194 mfp.data_dir &= ~1; 195 /* MFP port I0 interrupt on high->low edge. */ 196 mfp.active_edge &= ~1; 197 p = parport_register_port((unsigned long)&sound_ym.wd_data, 198 IRQ_MFP_BUSY, PARPORT_DMA_NONE, 199 &parport_atari_ops); 200 if (!p) 201 return -ENODEV; 202 if (request_irq(IRQ_MFP_BUSY, parport_atari_interrupt, 203 IRQ_TYPE_SLOW, p->name, p)) { 204 parport_put_port (p); 205 return -ENODEV; 206 } 207 208 this_port = p; 209 printk(KERN_INFO "%s: Atari built-in port using irq\n", p->name); 210 parport_announce_port (p); 211 212 return 0; 213 } 214 return -ENODEV; 215} 216 217static void __exit parport_atari_exit(void) 218{ 219 parport_remove_port(this_port); 220 if (this_port->irq != PARPORT_IRQ_NONE) 221 free_irq(IRQ_MFP_BUSY, this_port); 222 parport_put_port(this_port); 223} 224 225MODULE_AUTHOR("Andreas Schwab"); 226MODULE_DESCRIPTION("Parport Driver for Atari builtin Port"); 227MODULE_SUPPORTED_DEVICE("Atari builtin Parallel Port"); 228MODULE_LICENSE("GPL"); 229 230module_init(parport_atari_init) 231module_exit(parport_atari_exit) 232