460 Notes on Printer
Parallel Printer Info:
IRQ7 ==> Vector 15
LPT1: LPT2:
----- -----
1. DATA register = 0x378 0x3BC
2. STATUS reg: 0x379 0x3BD
3. COMMAND reg: 0x37A 0x3BE
=====================================================================
4. Status Register Contents:
7 6 5 4 3 2 1 0
NOTBUSY - NOPAPER SELECT NOERROR - - -
------- --------- -------- ----------
1=READY 1=NOPAPER 1=OnLine 1=NOERROR
0=BUSY 0=Paper 0=not 0=ERROR
-----------------------------------------------------------------
5. Command Register Usage:
7 6 5 4 3 2 1 0
- - - EnableIRQ INIT SELECT STROBE
-----------------------------------------------------------------------
Before printing, the printer must be initialized once by :
(1) To INIT : write 0x08 to COMMAND reg first. Then
(2). To select : write 0x0C to COMMAND reg.
--------------------------------------------------------------------------
After writing a char to DATA register, must strobe once by
writing to bit0 a 1 followed by a 0.
NO interrupts:
write 0x0D = 0000 1101 followed by
0x0C = 0000 1100.
With interrupts:
write 0x1D = 0001 1101 followed by
0x1C = 0001 1100
strobe width > 0.5 usec
---------------------------------------------------------------------------
Printer Driver Design:
(1). main():
main()
{
lock();
init();
myfork();
set_vector(80, int80h);
set_vector(15, pinth); // set vector 15 ==> (PC,CS)=(pinth, 0x1000)
pr_init(); // initialize printer
tswitch();
}
(2). pr_init():
char pbuf[128]; // contain data to print
int index plen; // bytes pointer and length
pr_init()
{
index=plen=0;
/* initialize printer at PORT=0x3F8 OR 0x3BC */
out_byte(PORT+2, 0x08); /* init */
out_byte(PORT+2, 0x0C); /* int, init, select on */
enable_irq(7); /* set bit_7 of 0x21 to 0 ==> unmask INQ7 */
}
(3). Install vector (15) and interrupt handler:
In t.c:
Set Vector 15 = (pinth, 0x1000) = (PC, CS)
In ts.s:
_pinth: INTH phandler ! use INTH macro for _pinth
(4). phandler() in C:
int phandler()
{
int status = in_byte(PORT+1);
if ((status & 0xB0) == 0x90){ // printer READY
if (++index >= plen){ // all chars have been printed
out_byte(PORT+2, 0x0C); // turn off printer INT bit
goto out;
}
// output next char
out_byte(PORT, pbuf[index]; // out char
out_byte(PORT+2, 0x1D); // strobe
delay();
out_byte(PORT+2, 0x1C);
goto out;
}
// abnormal status, e.g. off-line, no-paper, error, etc.
// deal with it (ignored here)
out:
out_byte(0x20, 0x20); // re-enable 8259
}
==============================================================================
(5). Upper HALF of Printer Driver (Kernel function, called by process).
kpline(line) char *line; // print a line in Kernel
{
strcpy(pbuf, line);
plen = strlen(pbuf); index = 0;
// output first char
out_byte(PORT, pbuf[0]);
out_byte(PORT+2, 0x1D); // strobe with interrupt bit on
delay();
put_byte(PORT+2, 0x1C); // interrupt handler will print the rest of pbuf[]
}
============================================================================
Print lines from Umode:
syscall(#, uline, 0, 0); // uline -> a string in Umode
kcinth()
{
case # : puline(uline); break;
}
int puline(b) char *b;
{
char kline[128];
get line from Umode;
kpline(kline); // call driver kpline() in Kernel
}
============================================================================
POSTED FILE:
~samples/PRINTER/printer.c
Use this file to develop a printer driver for MTX.
Printer:
In Sloan 327 Lab: The 2nd PC has a HP 840 Deskjet printer.
The 3rd PC has a Canon 4300 Inkjet printer.
Both printers are installed at PORT 0x378
===========================================================================
Refinement of the printer driver:
Lecture and Questions.