1 /* Low-level parallel port routines for the Amiga built-in port 2 * 3 * Author: Joerg Dorchain <joerg@dorchain.net> 4 * 5 * This is a complete rewrite of the code, but based heaviy upon the old 6 * lp_intern. code. 7 * 8 * The built-in Amiga parallel port provides one port at a fixed address 9 * with 8 bidirectional data lines (D0 - D7) and 3 bidirectional status 10 * lines (BUSY, POUT, SEL), 1 output control line /STROBE (raised automatically 11 * in hardware when the data register is accessed), and 1 input control line 12 * /ACK, able to cause an interrupt, but both not directly settable by 13 * software. 14 */ 15 16 #include <linux/module.h> 17 #include <linux/init.h> 18 #include <linux/parport.h> 19 #include <linux/ioport.h> 20 #include <linux/interrupt.h> 21 #include <asm/setup.h> 22 #include <asm/amigahw.h> 23 #include <asm/irq.h> 24 #include <asm/io.h> 25 #include <asm/amigaints.h> 26 27 #undef DEBUG 28 #ifdef DEBUG 29 #define DPRINTK printk 30 #else 31 #define DPRINTK(x...) do { } while (0) 32 #endif 33 34 static struct parport *this_port = NULL; 35 36 static void amiga_write_data(struct parport *p, unsigned char data) 37 { 38 DPRINTK(KERN_DEBUG "write_data %c\n",data); 39 /* Triggers also /STROBE. This behavior cannot be changed */ 40 ciaa.prb = data; 41 mb(); 42 } 43 44 static unsigned char amiga_read_data(struct parport *p) 45 { 46 /* Triggers also /STROBE. This behavior cannot be changed */ 47 return ciaa.prb; 48 } 49 50 #if 0 51 static unsigned char control_pc_to_amiga(unsigned char control) 52 { 53 unsigned char ret = 0; 54 55 if (control & PARPORT_CONTROL_SELECT) /* XXX: What is SELECP? */ 56 ; 57 if (control & PARPORT_CONTROL_INIT) /* INITP */ 58 /* reset connected to cpu reset pin */; 59 if (control & PARPORT_CONTROL_AUTOFD) /* AUTOLF */ 60 /* Not connected */; 61 if (control & PARPORT_CONTROL_STROBE) /* Strobe */ 62 /* Handled only directly by hardware */; 63 return ret; 64 } 65 #endif 66 67 static unsigned char control_amiga_to_pc(unsigned char control) 68 { 69 return PARPORT_CONTROL_SELECT | 70 PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_STROBE; 71 /* fake value: interrupt enable, select in, no reset, 72 no autolf, no strobe - seems to be closest the wiring diagram */ 73 } 74 75 static void amiga_write_control(struct parport *p, unsigned char control) 76 { 77 DPRINTK(KERN_DEBUG "write_control %02x\n",control); 78 /* No implementation possible */ 79 } 80 81 static unsigned char amiga_read_control( struct parport *p) 82 { 83 DPRINTK(KERN_DEBUG "read_control \n"); 84 return control_amiga_to_pc(0); 85 } 86 87 static unsigned char amiga_frob_control( struct parport *p, unsigned char mask, unsigned char val) 88 { 89 unsigned char old; 90 91 DPRINTK(KERN_DEBUG "frob_control mask %02x, value %02x\n",mask,val); 92 old = amiga_read_control(p); 93 amiga_write_control(p, (old & ~mask) ^ val); 94 return old; 95 } 96 97 #if 0 /* currently unused */ 98 static unsigned char status_pc_to_amiga(unsigned char status) 99 { 100 unsigned char ret = 1; 101 102 if (status & PARPORT_STATUS_BUSY) /* Busy */ 103 ret &= ~1; 104 if (status & PARPORT_STATUS_ACK) /* Ack */ 105 /* handled in hardware */; 106 if (status & PARPORT_STATUS_PAPEROUT) /* PaperOut */ 107 ret |= 2; 108 if (status & PARPORT_STATUS_SELECT) /* select */ 109 ret |= 4; 110 if (status & PARPORT_STATUS_ERROR) /* error */ 111 /* not connected */; 112 return ret; 113 } 114 #endif 115 116 static unsigned char status_amiga_to_pc(unsigned char status) 117 { 118 unsigned char ret = PARPORT_STATUS_BUSY | PARPORT_STATUS_ACK | PARPORT_STATUS_ERROR; 119 120 if (status & 1) /* Busy */ 121 ret &= ~PARPORT_STATUS_BUSY; 122 if (status & 2) /* PaperOut */ 123 ret |= PARPORT_STATUS_PAPEROUT; 124 if (status & 4) /* Selected */ 125 ret |= PARPORT_STATUS_SELECT; 126 /* the rest is not connected or handled autonomously in hardware */ 127 128 return ret; 129 } 130 131 static unsigned char amiga_read_status(struct parport *p) 132 { 133 unsigned char status; 134 135 status = status_amiga_to_pc(ciab.pra & 7); 136 DPRINTK(KERN_DEBUG "read_status %02x\n", status); 137 return status; 138 } 139 140 /* as this ports irq handling is already done, we use a generic funktion */ 141 static irqreturn_t amiga_interrupt(int irq, void *dev_id, struct pt_regs *regs) 142 { 143 parport_generic_irq(irq, (struct parport *) dev_id, regs); 144 return IRQ_HANDLED; 145 } 146 147 static void amiga_enable_irq(struct parport *p) 148 { 149 enable_irq(IRQ_AMIGA_CIAA_FLG); 150 } 151 152 static void amiga_disable_irq(struct parport *p) 153 { 154 disable_irq(IRQ_AMIGA_CIAA_FLG); 155 } 156 157 static void amiga_data_forward(struct parport *p) 158 { 159 DPRINTK(KERN_DEBUG "forward\n"); 160 ciaa.ddrb = 0xff; /* all pins output */ 161 mb(); 162 } 163 164 static void amiga_data_reverse(struct parport *p) 165 { 166 DPRINTK(KERN_DEBUG "reverse\n"); 167 ciaa.ddrb = 0; /* all pins input */ 168 mb(); 169 } 170 171 static void amiga_init_state(struct pardevice *dev, struct parport_state *s) 172 { 173 s->u.amiga.data = 0; 174 s->u.amiga.datadir = 255; 175 s->u.amiga.status = 0; 176 s->u.amiga.statusdir = 0; 177 } 178 179 static void amiga_save_state(struct parport *p, struct parport_state *s) 180 { 181 mb(); 182 s->u.amiga.data = ciaa.prb; 183 s->u.amiga.datadir = ciaa.ddrb; 184 s->u.amiga.status = ciab.pra & 7; 185 s->u.amiga.statusdir = ciab.ddra & 7; 186 mb(); 187 } 188 189 static void amiga_restore_state(struct parport *p, struct parport_state *s) 190 { 191 mb(); 192 ciaa.prb = s->u.amiga.data; 193 ciaa.ddrb = s->u.amiga.datadir; 194 ciab.pra |= (ciab.pra & 0xf8) | s->u.amiga.status; 195 ciab.ddra |= (ciab.ddra & 0xf8) | s->u.amiga.statusdir; 196 mb(); 197 } 198 199 static struct parport_operations pp_amiga_ops = { 200 .write_data = amiga_write_data, 201 .read_data = amiga_read_data, 202 203 .write_control = amiga_write_control, 204 .read_control = amiga_read_control, 205 .frob_control = amiga_frob_control, 206 207 .read_status = amiga_read_status, 208 209 .enable_irq = amiga_enable_irq, 210 .disable_irq = amiga_disable_irq, 211 212 .data_forward = amiga_data_forward, 213 .data_reverse = amiga_data_reverse, 214 215 .init_state = amiga_init_state, 216 .save_state = amiga_save_state, 217 .restore_state = amiga_restore_state, 218 219 .epp_write_data = parport_ieee1284_epp_write_data, 220 .epp_read_data = parport_ieee1284_epp_read_data, 221 .epp_write_addr = parport_ieee1284_epp_write_addr, 222 .epp_read_addr = parport_ieee1284_epp_read_addr, 223 224 .ecp_write_data = parport_ieee1284_ecp_write_data, 225 .ecp_read_data = parport_ieee1284_ecp_read_data, 226 .ecp_write_addr = parport_ieee1284_ecp_write_addr, 227 228 .compat_write_data = parport_ieee1284_write_compat, 229 .nibble_read_data = parport_ieee1284_read_nibble, 230 .byte_read_data = parport_ieee1284_read_byte, 231 232 .owner = THIS_MODULE, 233 }; 234 235 /* ----------- Initialisation code --------------------------------- */ 236 237 static int __init parport_amiga_init(void) 238 { 239 struct parport *p; 240 int err; 241 242 if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_PARALLEL)) 243 return -ENODEV; 244 245 err = -EBUSY; 246 if (!request_mem_region(CIAA_PHYSADDR-1+0x100, 0x100, "parallel")) 247 goto out_mem; 248 249 ciaa.ddrb = 0xff; 250 ciab.ddra &= 0xf8; 251 mb(); 252 253 p = parport_register_port((unsigned long)&ciaa.prb, IRQ_AMIGA_CIAA_FLG, 254 PARPORT_DMA_NONE, &pp_amiga_ops); 255 if (!p) 256 goto out_port; 257 258 err = request_irq(IRQ_AMIGA_CIAA_FLG, amiga_interrupt, 0, p->name, p); 259 if (err) 260 goto out_irq; 261 262 this_port = p; 263 printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name); 264 /* XXX: set operating mode */ 265 parport_announce_port(p); 266 267 return 0; 268 269 out_irq: 270 parport_put_port(p); 271 out_port: 272 release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100); 273 out_mem: 274 return err; 275 } 276 277 static void __exit parport_amiga_exit(void) 278 { 279 parport_remove_port(this_port); 280 if (this_port->irq != PARPORT_IRQ_NONE) 281 free_irq(IRQ_AMIGA_CIAA_FLG, this_port); 282 parport_put_port(this_port); 283 release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100); 284 } 285 286 287 MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>"); 288 MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port"); 289 MODULE_SUPPORTED_DEVICE("Amiga builtin Parallel Port"); 290 MODULE_LICENSE("GPL"); 291 292 module_init(parport_amiga_init) 293 module_exit(parport_amiga_exit) 294