aboutsummaryrefslogtreecommitdiff
path: root/printer.c
blob: 60e96e3b19089dc2f2659484bf9b9fa69139f6af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/**
 *  Operating Systems
 *  Mod 6
 *  Averill and Ben
 *  Writing awesome printer stuff.
 */

#include <dos.h>
#include <stdio.h>
#include "mpx.h";

void interrupt (*vect0f)();

int prt_opened;

int prt_open(int * prt_flag) {
  unsigned char imr;

  disable();

  if (prt_opened == NULL || prt_opened == 0) {
	prt_opened = 1;
  } else {
	return -2;
  }

  // set up vector interrupt
  vect0f = getvect(0x0f);
  setvect(0x0f, &prt_int);

  // enable printer interrupts on 8259
  imr = inportb(IMR);
  imr = imr & 0x7f; //0111-1111
  outportb(IMR, imr);

  // clear init bit (b2), set select bit (b3)
  // 0000 1010
  outportb(PCR, 0x0a);

  // initialize a printer control block
  prt.current_op = NO_OP;
  prt.event_flag = prt_flag;
  prt.count = 0;

  enable();
  return 0;
}

int prt_write(char far *buffer, int far *length) {

  disable();
  // check that prt isn't busy
  if (prt.current_op != NO_OP) {
	return -2;
  }

  // check that length is valid
  if (*length < 1) {
	return -3;
  }

  //save buffer and length in prt dcb
  prt.buffer = buffer;
  prt.length = length;
  prt.current_op = WRITE_OP;
  prt.count = 0;

  // enable printer interrupts on PCR
  // 0001 1010
  outportb(PCR, 0x1a);

  // strobe printer
  // 0001 1011
  outportb(PCR, 0x1d);

  // print a null
  // NOTE: something is not right here because when i print something
  // other than a null it still doesn't print
  outportb(PDR, 0x00);

  // unstrobe printer
  // 0001 1010
  outportb(PCR, 0x1c);

  enable();
  return 0;
}

int prt_close() {
  unsigned char imr;

  disable();

  // reset printer
  // set init bit (b2) to 1 all else clear
  // 0000 0100
  outportb(PCR, 0x04);

  //disable printer interrupts
  imr = inportb(IMR);
  imr = imr | 0x80;
  outportb(IMR, imr);

  // restore ms-dos's printer interrupt vector
  setvect(0x0f, vect0f);

  enable();
  return 0;
}

void interrupt prt_int() {
  unsigned char pcr;
  int *lst_stk;

  disable();
  lst_stk = _BP;

  // if no more char to write
  if (prt.count == *(prt.length)) {
	// disable printer interrupts at PCR
	// clear b4 on PCR
	pcr = inportb(PCR);
	pcr = pcr & 0xef; // 1110-1111
	outportb(PCR, pcr);

	// set event flag
	prt.current_op = NO_OP;
	*(prt.event_flag) = 1;

	// call io-complete
	IO_complete(PRT, lst_stk);

	// send end of interrupt signal
	outportb(0x20, 0x20);
  } else {

	// strobe printer
	// 0001 1101
	outportb(PCR, 0x1d);

	// write char to PDR
	outportb(PDR, prt.buffer[prt.count]);
	prt.count++;

	// unstrobe printer
	// 0001 1100
	outportb(PCR, 0x1c);
  }

  // send EOI
  outportb(0x20, 0x20);
  enable();
}