📄 parport.h
字号:
/**************************************************** * parport.h based on parport.h * * & * * ieee1284_ops.h * Copyright (C) Tim Waugh * tim&cyberelk.demon.co.uk ****************************************************//**************************************************** * Pins breakdown * * Data 0-7 PA 0-7 * Status 3-7 PB 3-7 * Control 0-1 PC 4-7 * Direction(Control 5) - PB 0 * refer to schematics.pdf *****************************************************/#define TIMEOUT 50000#define PARPORT_CONTROL_STROBE 0x1#define PARPORT_CONTROL_AUTOFD 0x2#define PARPORT_CONTROL_INIT 0x4#define PARPORT_CONTROL_SELECT 0x8#define PARPORT_STATUS_ERROR 0x8#define PARPORT_STATUS_SELECT 0x10#define PARPORT_STATUS_PAPEROUT 0x20#define PARPORT_STATUS_ACK 0x40#define PARPORT_STATUS_BUSY 0x80/* registers */typedef struct { /* 0 */ byte status; /* 1 */ byte ctr; /* 2 */ byte mode; /* 3 */ /* data register */ /* 4 */ byte expected; /* 5 */ byte main_state; /* 6 */ byte irq_state; /* 7 */ byte done; /* 8 */ byte mask_status; /* 9 */ byte old_status; /* A */ byte irq_status; } registers_1284;static data registers_1284 reg_1284; #define __parport_frob_control(mask, value) reg_1284.ctr=(reg_1284.ctr & ~mask)^value;/* parport operations * * parport_write_data * parport_read_data * * parport_write_control * parport_read_control * parport_frob_control * * parport_read_status * * parport_enable_irq * parport_disable_irq * * parport_data_forward * parport_data_reverse * * parport_init_state * parport_save_state * parport_restore_state * * parport_epp_write_data * parport_epp_read_data * parport_epp_write_addr * parport_epp_read_addr * * parport_ecp_write_data * parport_ecp_read_data * parport_ecp_write_addr * * parport_write_compat * parport_read_nibble * parport_read_byte */#define w __parport_frob_control(mask, value) (mask = value)static void parport_write_data(byte d){ OUTA = d;}static byte parport_read_data(void){ return PINSA;}static void parport_write_control(byte d){ byte wm = ( PARPORT_CONTROL_STROBE | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_INIT | PARPORT_CONTROL_SELECT); __parport_frob_control(wm, d & wm); wm = wm << 4; d = d << 4; OUTC = (OUTC & ~wm)^d; } static byte parport_read_control(void){ /* soft copy will do */ return reg_1284.ctr;}static byte parport_frob_control(byte mask, byte value){ const byte wm = (PARPORT_CONTROL_STROBE | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_INIT | PARPORT_CONTROL_SELECT); mask &= wm; value &= wm; __parport_frob_control(mask,value); mask = mask << 4; value = value << 4; OUTC = (OUTC & ~mask)^value; }static byte parport_read_status(void){ const byte wm = (PARPORT_STATUS_ERROR | PARPORT_STATUS_SELECT | PARPORT_STATUS_PAPEROUT| PARPORT_STATUS_ACK | PARPORT_STATUS_BUSY); reg_1284.status = reg_1284.status & ~wm; reg_1284.status ^= PINSB & wm; return reg_1284.status;}static void parport_disable_irq(void){ __parport_frob_control(0x10,0);}static void parport_enable_irq(void){ __parport_frob_control(0x10,0x10);}static void parport_data_forward(void){ __parport_frob_control(0x20,0); OEA = 0xFF; OUTB &= 0xFE;}static void parport_data_reverse(void){ __parport_frob_control(0x20,0x20); OEA = 0; OUTB |=0x01;}/* compatibility mode */static byte parport_write_compat(byte * buffer, byte len){ byte count = 0; byte dt = 0; byte sts; byte * addr = buffer; parport_write_control(PARPORT_CONTROL_SELECT| PARPORT_CONTROL_INIT); parport_data_forward(); /* start transmission */ while(count < len){ timeafter(TIMEOUT); /* wait for the peripheral */ while(!__timeafter){ /* is peripheral ready ? */ sts = parport_read_status(); sts &= PARPORT_STATUS_BUSY | PARPORT_STATUS_ERROR; sts ^= PARPORT_STATUS_BUSY | PARPORT_STATUS_ERROR; if(!sts) goto ready; /* is peripheral upset ? */ sts = parport_read_status(); sts &= PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR; if(sts != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) goto stop; } /* timeout after all */ return count; ready: dt = *addr; addr++; parport_write_data(dt); udelay(10); /* pulse strobe */ sts = parport_read_control(); sts |= PARPORT_CONTROL_STROBE; parport_write_control(sts); udelay(10); sts &= ~PARPORT_CONTROL_STROBE; parport_write_control(sts); count ++; } stop: return count;}/* nibble mode */static byte parport_read_nibble(byte * buffer, byte len){ byte count; byte * addr = buffer; byte sts; byte dt = 0; byte nibble; len *= 2; for (count = 0; count < len; count ++){ timeafter(TIMEOUT); /* end of data */ if((count & 0x01) == 0){ sts = parport_read_status(); if(sts & PARPORT_STATUS_ERROR){ parport_frob_control(PARPORT_CONTROL_AUTOFD,0); return(count/2); } } /* set autofd low */ parport_frob_control(PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD); while(!__timeafter){ sts = parport_read_status(); if(!(sts & PARPORT_STATUS_ACK)) goto read; } /* time out */ return (count/2); /* read nibble */ read: nibble = parport_read_status() >> 3; nibble &= ~8; if((nibble & 0x10) == 0) nibble |= 8; nibble &= 0x0F; /* set autofd high */ parport_frob_control(PARPORT_CONTROL_AUTOFD,0); /* wait for nack */ timeafter(TIMEOUT); while(!__timeafter){ sts = parport_read_status(); /* nack goes high */ if(sts & PARPORT_STATUS_ACK) goto over; } /* timeout */ return (count/2); over: if(count & 1){ dt |= nibble <<4; *addr++ = dt; }else dt = nibble; } return (count/2);}/* epp forward channel, address */static byte parport_epp_write_addr (byte * buffer, byte len){ byte * addr = buffer; byte sts; byte dt = 0; byte count; parport_frob_control(PARPORT_CONTROL_STROBE | PARPORT_CONTROL_SELECT | PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_STROBE | PARPORT_CONTROL_SELECT); for (count = 0; count < len; count++){ dt = *addr; addr++; parport_write_data(dt); parport_frob_control(PARPORT_CONTROL_SELECT, PARPORT_CONTROL_SELECT); timeafter(TIMEOUT); while(!__timeafter){ sts = parport_read_status(); if((sts & PARPORT_STATUS_BUSY) == 0) goto ready; } /* timeout */ return count; ready: parport_frob_control (PARPORT_CONTROL_SELECT,0); while(1){ /* timeout */ if(__timeafter) return count; sts = parport_read_status(); if(sts & PARPORT_STATUS_BUSY) break; } } parport_frob_control(PARPORT_CONTROL_STROBE, 0); return count;}/* epp forward channel, data */static byte parport_epp_write_data (byte * buffer, byte len){ byte * addr = buffer; byte sts; byte dt = 0; byte count; parport_frob_control(PARPORT_CONTROL_STROBE | PARPORT_CONTROL_SELECT | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_INIT, PARPORT_CONTROL_STROBE | PARPORT_CONTROL_INIT); for (count = 0; count < len; count++){ dt = *addr; addr++; parport_write_data(dt); parport_frob_control(PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD); timeafter(TIMEOUT); while(!__timeafter){ sts = parport_read_status(); if((sts & PARPORT_STATUS_BUSY) == 0) goto ready; } /* timeout */ return count; ready: parport_frob_control (PARPORT_CONTROL_AUTOFD,0); while(1){ /* timeout */ if(__timeafter) return count; sts = parport_read_status(); if(sts & PARPORT_STATUS_BUSY) break; } } parport_frob_control(PARPORT_CONTROL_STROBE, 0); return count;}/* epp mode, reverse channel, address *//* once done report the bug at ieee1284_ops.c */ static byte parport_epp_read_addr (byte * buffer, byte len){ byte * addr = buffer; byte sts; byte count; byte dt; parport_frob_control(PARPORT_CONTROL_STROBE | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_SELECT, 0); parport_data_reverse(); for(count = 0; count < len; count ++){ parport_frob_control(PARPORT_CONTROL_SELECT, PARPORT_CONTROL_SELECT); timeafter(TIMEOUT); while(1){ if(__timeafter) return count; sts = parport_read_status(); if((sts & PARPORT_STATUS_BUSY) == 0) break; } dt = parport_read_data(); *addr++ = dt; parport_frob_control(PARPORT_CONTROL_SELECT, 0); while(1){ if(__timeafter) return count; sts = parport_read_status(); if(sts & PARPORT_STATUS_BUSY) break; } } parport_data_forward(); return count;}/* epp mode, reverse channel, data */static byte parport_epp_read_data (byte * buffer, byte len){ byte * addr = buffer; byte sts; byte count; byte dt; parport_frob_control(PARPORT_CONTROL_STROBE | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_SELECT, 0); parport_data_reverse(); in0buf[6] = 0xee; for(count = 0; count < len; count ++){ parport_frob_control(PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD); timeafter(TIMEOUT); while(1){ if(__timeafter) return count; sts = parport_read_status(); if((sts & PARPORT_STATUS_BUSY) == 0) break; } dt = parport_read_data(); *addr++ = dt; parport_frob_control(PARPORT_CONTROL_AUTOFD, 0); while(1){ if(__timeafter) return count; sts = parport_read_status(); if(sts & PARPORT_STATUS_BUSY) break; } } parport_data_forward(); in0buf[6] = count; return count;}/******************************************** * I tested ecp part with a standalone MCU, * however I have no equipment to test it real * life, if you are interested in this part * try it with respective changes to the driver * and firmware ********************************************/#if 0/* ecp functions */static byte ecp_forward_to_reverse(){ byte sts; parport_frob_control(PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD); parport_data_reverse(); udelay(10); parport_frob_control(PARPORT_CONTROL_INIT,0); timeafter(100); while(1){ if (__timeafter) return 1; sts = parport_read_status(); if((sts & PARPORT_STATUS_PAPEROUT) == 0) break; } return 0;}static byte ecp_reverse_to_forward(){ byte sts; parport_frob_control(PARPORT_CONTROL_INIT | PARPORT_CONTROL_STROBE, PARPORT_CONTROL_INIT); timeafter(100); while(1){ if(__timeafter) return 1; sts = parport_read_status(); if(sts & PARPORT_STATUS_PAPEROUT) break; } parport_data_forward(); return 0;}/* ecp mode, forward channel,data */static byte parport_ecp_write_data(byte * buffer, byte len){ byte * addr = buffer; byte count; byte sts; byte dt; /* direction of traffic */ if(ecp_reverse_to_forward()) return 0; /* HostAck high (data) */ parport_frob_control(PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_STROBE | PARPORT_CONTROL_INIT, PARPORT_CONTROL_INIT); for(count = 0; count < len; count ++){ dt = *addr; addr++; parport_write_data(dt); parport_frob_control(PARPORT_CONTROL_STROBE, PARPORT_CONTROL_STROBE); timeafter(TIMEOUT); while(1){ if(__timeafter) return count; sts = parport_read_status(); if((sts & PARPORT_STATUS_BUSY) == 0) break; } parport_frob_control(PARPORT_CONTROL_STROBE,0); while(1){ if(__timeafter) return count; sts = parport_read_status(); if(sts & PARPORT_STATUS_BUSY) break; } } return count;}/* ecp mode, forward channel, address */static byte parport_ecp_write_addr (byte * buffer, byte len){ byte * addr = buffer; byte count; byte sts; byte dt; /* direction of traffic */ if(ecp_reverse_to_forward()) { in0buf[6] = 0xcc; return 0;} /* HostAck high (address) */ parport_frob_control(PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_STROBE | PARPORT_CONTROL_INIT, PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_INIT); for(count = 0; count < len; count ++){ dt = *addr; addr++; parport_write_data(dt); parport_frob_control(PARPORT_CONTROL_STROBE, PARPORT_CONTROL_STROBE); timeafter(TIMEOUT); while(1){ if(__timeafter) { in0buf[6] = 0x66; return count; } sts = parport_read_status(); if((sts & PARPORT_STATUS_BUSY) == 0) break; } parport_frob_control(PARPORT_CONTROL_STROBE,0); while(1){ if(__timeafter) { in0buf[6] = 0x77; return count; } sts = parport_read_status(); if(sts & PARPORT_STATUS_BUSY) break; } } in0buf[6] = 0xaa; return count;}/* ecp mode, reverse channel, address */static byte parport_ecp_read_data (byte * buffer, byte len){ byte * addr = buffer; byte count; byte sts; byte dt; byte rle = 0; byte rle_count = 0; byte command =0; in0buf[6] = 0xee; if(ecp_forward_to_reverse()) {in0buf[6] = 0xDD; return 0;} /* HostAck low */ parport_frob_control(PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_STROBE | PARPORT_CONTROL_INIT, PARPORT_CONTROL_AUTOFD); for(count = 0; count < len; 0 ){ timeafter(TIMEOUT); while(1){ if(__timeafter) {in0buf[6] = 0x11; return count;} sts = parport_read_status(); if((sts & PARPORT_STATUS_ACK) == 0) break; } /* read data */ dt = parport_read_data(); /* is it data or command ? */ if(rle) command = 0; else{ sts = parport_read_status(); if(sts & PARPORT_STATUS_BUSY) command = 1; else command = 0; } if(command){ if(dt & 0x80) return count; rle_count = dt + 1; sts = len - count; if(rle_count > sts) return count; rle = 1; } parport_frob_control(PARPORT_CONTROL_AUTOFD,0); while(1){ if(__timeafter) return count; sts = parport_read_status(); if(sts & PARPORT_STATUS_ACK) break; } parport_frob_control(PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD); if(command) continue; if(rle){ rle = 0; memset(addr,dt,rle_count); count += rle_count; addr += rle_count; } else { * addr = dt; addr ++; count ++; } } in0buf[6] = count; return count;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -