Writing to a parallel port
Posted: Mon Oct 17, 2022 5:21 am
Hello. I noticed that the parallel port writing routine in the OSDev wiki does not work. The problem is that after the byte is sent to the printer, the code does not wait for the printer to become receptive again - instead it immediately reads the control port, which causes things to happen too fast. It may work on a virtual machine, but not on a real hardware.
I wrote my own parallel port write routine that is loosely based on the original IBM PC's BIOS listings. My code does not read the control port at all after sending the byte because it is not needed - instead it just reads the status port until the printer becomes receptive to new commands again. This code works and it has already proved itself, I very often do printing with it.
I wrote my own parallel port write routine that is loosely based on the original IBM PC's BIOS listings. My code does not read the control port at all after sending the byte because it is not needed - instead it just reads the status port until the printer becomes receptive to new commands again. This code works and it has already proved itself, I very often do printing with it.
Code: Select all
// a very short delay
void shortdelay(unsigned long interval);
unsigned short __far *parallelbase = (unsigned short __far*)0x00400008L;
// returns 0 if everything is ok
// returns 1 if there is no such parallel port
char parallel_init(unsigned short port, unsigned int mode)
{
unsigned short control_port = parallelbase[port]+2;
if(!parallelbase[port])
return 1;
// disable interrupts
outbyte(control_port, inbyte(control_port) & ~0x10);
// reset the device and select the device and set direction to write
outbyte(control_port, inbyte(control_port) & ~(0x04 | 0x20));
delay(50);
outbyte(control_port, inbyte(control_port) | 0x04 | 0x08);
// if mode is !0, switch auto line feed on (BIOS call does not do this!!)
if(mode & 0x00FF)
outbyte(control_port, inbyte(control_port) | 0x02);
delay(1000);
return 0;
}
// returns 0 if everything is OK
// returns 1 if a non-critical error happened (out of paper or something)
// returns 2 if a critical error happened
unsigned char parallel_write(unsigned short port, unsigned char chr)
{
unsigned char retval;
unsigned short control_port = parallelbase[port]+2;
unsigned short printer_port = parallelbase[port];
unsigned short status_port = parallelbase[port]+1;
unsigned short retries = 0;
if(inbyte(status_port) & 0x20)
return 1;
outbyte(printer_port, chr);
// this check and delay is essential - otherwise things happen too fast!!!
while(!(inbyte(status_port) & 0x80) && ++retries)
shortdelay(LPT_PULSE_DELAY);
retries = 0;
shortdelay(LPT_PULSE_DELAY);
outbyte(control_port, 0x0D);
shortdelay(LPT_PULSE_DELAY);
outbyte(control_port, 0x0C);
inbyte(status_port);
while(!(inbyte(status_port) & 0x80) && ++retries)
shortdelay(LPT_PULSE_DELAY);
if(!(inbyte(status_port) & 0x08))
return 2;
return 0;
}