Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
0880b18e | 2 | * Copyright (c) 1982, 1986 Regents of the University of California. |
da7c5cc6 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
15687812 | 6 | * @(#)dmf.c 7.2 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
7a17d042 SL |
8 | |
9 | #include "dmf.h" | |
10 | #if NDMF > 0 | |
11 | /* | |
12 | * DMF32 driver | |
13 | * | |
b660f54f | 14 | * |
7a17d042 SL |
15 | * TODO: |
16 | * test with modem | |
17 | * load as much as possible into silo | |
7a17d042 SL |
18 | * use auto XON/XOFF |
19 | * test reset code | |
b660f54f JB |
20 | **************************** |
21 | * DMF32 line printer driver | |
22 | * | |
23 | * the line printer on dmfx is indicated by a minor device code of 128+x | |
24 | * | |
25 | * the flags field of the config file is interpreted like so: | |
26 | * bits meaning | |
27 | * ---- ------- | |
28 | * 0-7 soft carrier bits for ttys part of dmf32 | |
29 | * 8-15 number of cols/line on the line printer | |
30 | * if 0, 132 will be used. | |
31 | * 16-23 number of lines/page on the line printer | |
32 | * if 0, 66 will be used. | |
3c808bd7 MK |
33 | * 24 if 1 DO NOT use the auto format mode of the |
34 | * line printer parallel port | |
7a17d042 | 35 | */ |
961945a8 SL |
36 | #include "../machine/pte.h" |
37 | ||
7a17d042 | 38 | #include "bk.h" |
66e92dcf | 39 | #include "uba.h" |
52163dab JB |
40 | #include "param.h" |
41 | #include "conf.h" | |
42 | #include "dir.h" | |
43 | #include "user.h" | |
0b35cf68 | 44 | #include "proc.h" |
52163dab JB |
45 | #include "ioctl.h" |
46 | #include "tty.h" | |
47 | #include "map.h" | |
48 | #include "buf.h" | |
49 | #include "vm.h" | |
50 | #include "bkmac.h" | |
51 | #include "clist.h" | |
52 | #include "file.h" | |
53 | #include "uio.h" | |
b660f54f | 54 | #include "kernel.h" |
b50ce881 | 55 | #include "syslog.h" |
7a17d042 | 56 | |
52163dab JB |
57 | #include "ubareg.h" |
58 | #include "ubavar.h" | |
59 | #include "dmfreg.h" | |
896962b1 | 60 | |
7a17d042 SL |
61 | /* |
62 | * Definition of the driver for the auto-configuration program. | |
63 | */ | |
64 | int dmfprobe(), dmfattach(), dmfrint(), dmfxint(); | |
b660f54f | 65 | int dmflint(); |
7a17d042 SL |
66 | struct uba_device *dmfinfo[NDMF]; |
67 | u_short dmfstd[] = { 0 }; | |
68 | struct uba_driver dmfdriver = | |
69 | { dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo }; | |
70 | ||
9c95d9b6 | 71 | int dmf_timeout = 10; /* silo timeout, in ms */ |
b660f54f JB |
72 | int dmf_mindma = 4; /* don't dma below this point */ |
73 | ||
7a17d042 SL |
74 | /* |
75 | * Local variables for the driver | |
76 | */ | |
77 | char dmf_speeds[] = | |
78 | { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 }; | |
79 | ||
9c95d9b6 MK |
80 | #ifndef PORTSELECTOR |
81 | #define ISPEED B9600 | |
82 | #define IFLAGS (EVENP|ODDP|ECHO) | |
83 | #else | |
84 | #define ISPEED B4800 | |
85 | #define IFLAGS (EVENP|ODDP) | |
86 | #endif | |
87 | ||
7a17d042 SL |
88 | struct tty dmf_tty[NDMF*8]; |
89 | char dmfsoftCAR[NDMF]; | |
b660f54f | 90 | |
8011f5df MK |
91 | struct dmfl_softc { |
92 | u_int dmfl_state; /* soft state bits */ | |
93 | int dmfl_info; /* uba info */ | |
94 | u_short dmfl_lines; /* lines per page (66 def.) */ | |
95 | u_short dmfl_cols; /* cols per line (132 def.) */ | |
3c808bd7 | 96 | u_short dmfl_format; /* fflag for auto form feed */ |
8011f5df | 97 | char dmfl_buf[DMFL_BUFSIZ]; |
b660f54f JB |
98 | } dmfl_softc[NDMF]; |
99 | ||
100 | /* | |
101 | * convert device number into DMF line printer unit number | |
102 | */ | |
103 | #define DMFL_UNIT(d) (minor(d)&0xF) /* up to 16 DMFs */ | |
104 | ||
105 | #define ASLP 1 /* waiting for interrupt from dmf */ | |
106 | #define OPEN 2 /* line printer is open */ | |
107 | #define ERROR 4 /* error while printing, driver | |
108 | refuses to do anything till closed */ | |
3c808bd7 | 109 | #define MOREIO 8 /* more data for printer */ |
b660f54f | 110 | |
39d536e6 BJ |
111 | #ifndef lint |
112 | int ndmf = NDMF*8; /* used by iostat */ | |
113 | #endif | |
7a17d042 SL |
114 | int dmfact; /* mask of active dmf's */ |
115 | int dmfstart(), ttrstrt(); | |
116 | ||
7a17d042 SL |
117 | /* |
118 | * The clist space is mapped by the driver onto each UNIBUS. | |
119 | * The UBACVT macro converts a clist space address for unibus uban | |
120 | * into an i/o space address for the DMA routine. | |
121 | */ | |
66e92dcf | 122 | int dmf_ubinfo[NUBA]; /* info about allocated unibus map */ |
9c95d9b6 | 123 | int cbase[NUBA]; /* base address in unibus map */ |
7a17d042 | 124 | #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree)) |
b660f54f | 125 | char dmf_dma[NDMF*8]; |
7a17d042 SL |
126 | |
127 | /* | |
128 | * Routine for configuration to set dmf interrupt. | |
129 | */ | |
130 | /*ARGSUSED*/ | |
131 | dmfprobe(reg, ctlr) | |
132 | caddr_t reg; | |
b660f54f | 133 | struct uba_device *ctlr; |
7a17d042 SL |
134 | { |
135 | register int br, cvec; /* these are ``value-result'' */ | |
136 | register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg; | |
b660f54f JB |
137 | register int i; |
138 | register unsigned int a; | |
139 | static char *dmfdevs[]= | |
140 | {"parallel","printer","synch","asynch"}; | |
141 | unsigned int dmfoptions; | |
9c95d9b6 | 142 | static int (*intrv[3])() = { (int (*)())0, (int (*)())0, (int (*)())0 }; |
7a17d042 SL |
143 | |
144 | #ifdef lint | |
145 | br = 0; cvec = br; br = cvec; | |
bbee7e10 | 146 | dmfxint(0); dmfrint(0); |
8011f5df | 147 | dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(0); |
7a17d042 | 148 | #endif |
b660f54f JB |
149 | /* |
150 | * Pick the usual size DMF vector here (don't decrement it here). | |
151 | * grab configuration; note that the DMF32 | |
152 | * doesn't seem to put the right bits in this | |
153 | * register until AFTER the interrupt vector is set. | |
154 | */ | |
7a17d042 | 155 | br = 0x15; |
b660f54f | 156 | cvec = (uba_hd[numuba].uh_lastiv - 4*8); |
9c95d9b6 | 157 | dmfaddr->dmfccsr0 = (cvec >> 2); |
b660f54f JB |
158 | dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK; |
159 | ||
160 | /* catch a couple of special cases: Able vmz/32n and vmz/lp */ | |
161 | if (dmfoptions == DMFC_ASYNC) { | |
9c95d9b6 MK |
162 | /* Async portion only */ |
163 | ||
164 | cvec = (uba_hd[numuba].uh_lastiv -= 8); | |
165 | dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2; | |
166 | intrv[0] = ctlr->ui_intr[4]; | |
167 | intrv[1] = ctlr->ui_intr[5]; | |
168 | ctlr->ui_intr = intrv; | |
0840b085 | 169 | } else if (dmfoptions == DMFC_LP) { |
9c95d9b6 | 170 | /* LP portion only */ |
b660f54f | 171 | |
9c95d9b6 MK |
172 | cvec = (uba_hd[numuba].uh_lastiv -= 8); |
173 | ctlr->ui_intr = &ctlr->ui_intr[6]; | |
0840b085 | 174 | } else if (dmfoptions == (DMFC_LP|DMFC_ASYNC)) { |
9c95d9b6 MK |
175 | /* LP ans Async portions only */ |
176 | ||
177 | cvec = (uba_hd[numuba].uh_lastiv -= 2*8); | |
178 | ctlr->ui_intr = &ctlr->ui_intr[4]; | |
0840b085 | 179 | } else { |
9c95d9b6 | 180 | /* All other configurations get everything */ |
b660f54f JB |
181 | |
182 | cvec = (uba_hd[numuba].uh_lastiv -= 4*8); | |
b660f54f | 183 | } |
9c95d9b6 MK |
184 | a = (dmfoptions >> 12) & 0xf; |
185 | printf("dmf%d:", ctlr->ui_unit); | |
0840b085 MK |
186 | for (i = 0; a != 0; ++i, a >>= 1) { |
187 | if (a & 1) | |
9c95d9b6 MK |
188 | printf(" %s",dmfdevs[i]); |
189 | } | |
190 | printf(".\n"); | |
b660f54f JB |
191 | |
192 | if (dmfoptions & DMFC_LP) | |
15ad1ce4 | 193 | dmfaddr->dmfl_ctrl = DMFL_RESET; |
9c0adba0 | 194 | return (sizeof (struct dmfdevice)); |
7a17d042 SL |
195 | } |
196 | ||
197 | /* | |
198 | * Routine called to attach a dmf. | |
199 | */ | |
200 | dmfattach(ui) | |
201 | struct uba_device *ui; | |
202 | { | |
b660f54f JB |
203 | register int cols = (ui->ui_flags>>8) & 0xff; |
204 | register int lines = (ui->ui_flags>>16) & 0xff; | |
7a17d042 | 205 | |
b660f54f | 206 | dmfsoftCAR[ui->ui_unit] = ui->ui_flags & 0xff; |
26505102 MK |
207 | dmfl_softc[ui->ui_unit].dmfl_cols = cols == 0 ? DMFL_DEFCOLS : cols; |
208 | dmfl_softc[ui->ui_unit].dmfl_lines = lines == 0 ? DMFL_DEFLINES : lines; | |
3c808bd7 MK |
209 | if ((ui->ui_flags >> 24) & 0x1) |
210 | dmfl_softc[ui->ui_unit].dmfl_format = (2 << 8); | |
211 | else | |
212 | dmfl_softc[ui->ui_unit].dmfl_format = (2 << 8) | DMFL_FORMAT; | |
27f8c1d5 | 213 | cbase[ui->ui_ubanum] = -1; |
7a17d042 SL |
214 | } |
215 | ||
216 | ||
217 | /* | |
218 | * Open a DMF32 line, mapping the clist onto the uba if this | |
219 | * is the first dmf on this uba. Turn on this dmf if this is | |
220 | * the first use of it. | |
221 | */ | |
222 | /*ARGSUSED*/ | |
223 | dmfopen(dev, flag) | |
224 | dev_t dev; | |
225 | { | |
226 | register struct tty *tp; | |
227 | register int unit, dmf; | |
228 | register struct dmfdevice *addr; | |
229 | register struct uba_device *ui; | |
230 | int s; | |
231 | ||
232 | unit = minor(dev); | |
0840b085 MK |
233 | if (unit & 0200) |
234 | return (dmflopen(dev,flag)); | |
7a17d042 | 235 | dmf = unit >> 3; |
7da157da BJ |
236 | if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0) |
237 | return (ENXIO); | |
7a17d042 | 238 | tp = &dmf_tty[unit]; |
7da157da BJ |
239 | if (tp->t_state&TS_XCLUDE && u.u_uid!=0) |
240 | return (EBUSY); | |
7a17d042 SL |
241 | addr = (struct dmfdevice *)ui->ui_addr; |
242 | tp->t_addr = (caddr_t)addr; | |
243 | tp->t_oproc = dmfstart; | |
c38b985f | 244 | tp->t_state |= TS_WOPEN; |
7a17d042 SL |
245 | /* |
246 | * While setting up state for this uba and this dmf, | |
247 | * block uba resets which can clear the state. | |
248 | */ | |
b660f54f | 249 | s = spltty(); |
27f8c1d5 | 250 | if (cbase[ui->ui_ubanum] == -1) { |
7a17d042 SL |
251 | dmf_ubinfo[ui->ui_ubanum] = |
252 | uballoc(ui->ui_ubanum, (caddr_t)cfree, | |
253 | nclist*sizeof(struct cblock), 0); | |
27f8c1d5 | 254 | cbase[ui->ui_ubanum] = UBAI_ADDR(dmf_ubinfo[ui->ui_ubanum]); |
7a17d042 | 255 | } |
7a17d042 SL |
256 | if ((dmfact&(1<<dmf)) == 0) { |
257 | addr->dmfcsr |= DMF_IE; | |
258 | dmfact |= (1<<dmf); | |
b660f54f | 259 | addr->dmfrsp = dmf_timeout; |
7a17d042 SL |
260 | } |
261 | splx(s); | |
262 | /* | |
3c808bd7 | 263 | * If this is first open, initialize tty state to default. |
7a17d042 | 264 | */ |
c38b985f | 265 | if ((tp->t_state&TS_ISOPEN) == 0) { |
7a17d042 | 266 | ttychars(tp); |
26505102 | 267 | #ifndef PORTSELECTOR |
3c808bd7 | 268 | if (tp->t_ispeed == 0) { |
26505102 MK |
269 | #else |
270 | tp->t_state |= TS_HUPCLS; | |
271 | #endif PORTSELECTOR | |
3c808bd7 MK |
272 | tp->t_ispeed = ISPEED; |
273 | tp->t_ospeed = ISPEED; | |
274 | tp->t_flags = IFLAGS; | |
26505102 | 275 | #ifndef PORTSELECTOR |
3c808bd7 | 276 | } |
26505102 | 277 | #endif PORTSELECTOR |
7a17d042 SL |
278 | dmfparam(unit); |
279 | } | |
280 | /* | |
281 | * Wait for carrier, then process line discipline specific open. | |
282 | */ | |
b660f54f | 283 | s = spltty(); |
3c808bd7 MK |
284 | for (;;) { |
285 | if ((dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8)) || | |
286 | (dmfsoftCAR[dmf] & (1<<(unit&07)))) | |
287 | tp->t_state |= TS_CARR_ON; | |
288 | if (tp->t_state & TS_CARR_ON) | |
289 | break; | |
c38b985f | 290 | tp->t_state |= TS_WOPEN; |
7a17d042 SL |
291 | sleep((caddr_t)&tp->t_rawq, TTIPRI); |
292 | } | |
293 | splx(s); | |
7da157da | 294 | return ((*linesw[tp->t_line].l_open)(dev, tp)); |
7a17d042 SL |
295 | } |
296 | ||
297 | /* | |
298 | * Close a DMF32 line. | |
299 | */ | |
300 | /*ARGSUSED*/ | |
301 | dmfclose(dev, flag) | |
302 | dev_t dev; | |
303 | int flag; | |
304 | { | |
305 | register struct tty *tp; | |
306 | register unit; | |
307 | ||
308 | unit = minor(dev); | |
0840b085 MK |
309 | if (unit & 0200) { |
310 | dmflclose(dev,flag); | |
311 | return; | |
312 | } | |
b660f54f | 313 | |
7a17d042 SL |
314 | tp = &dmf_tty[unit]; |
315 | (*linesw[tp->t_line].l_close)(tp); | |
6e7edb25 | 316 | (void) dmfmctl(unit, DMF_BRK, DMBIC); |
c38b985f | 317 | if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) |
6e7edb25 | 318 | (void) dmfmctl(unit, DMF_OFF, DMSET); |
7a17d042 SL |
319 | ttyclose(tp); |
320 | } | |
321 | ||
740e4029 | 322 | dmfread(dev, uio) |
7a17d042 | 323 | dev_t dev; |
740e4029 | 324 | struct uio *uio; |
7a17d042 SL |
325 | { |
326 | register struct tty *tp; | |
327 | ||
0840b085 | 328 | if (minor(dev) & 0200) |
b660f54f | 329 | return(ENXIO); |
7a17d042 | 330 | tp = &dmf_tty[minor(dev)]; |
740e4029 | 331 | return ((*linesw[tp->t_line].l_read)(tp, uio)); |
7a17d042 SL |
332 | } |
333 | ||
406ddcbe | 334 | dmfwrite(dev, uio) |
7a17d042 | 335 | dev_t dev; |
406ddcbe | 336 | struct uio *uio; |
7a17d042 SL |
337 | { |
338 | register struct tty *tp; | |
339 | ||
0840b085 MK |
340 | if (minor(dev) & 0200) |
341 | return (dmflwrite(dev,uio)); | |
7a17d042 | 342 | tp = &dmf_tty[minor(dev)]; |
078d920f | 343 | return ((*linesw[tp->t_line].l_write)(tp, uio)); |
7a17d042 SL |
344 | } |
345 | ||
346 | /* | |
347 | * DMF32 receiver interrupt. | |
348 | */ | |
349 | dmfrint(dmf) | |
350 | int dmf; | |
351 | { | |
7a17d042 | 352 | register c; |
0840b085 | 353 | register struct tty *tp; |
7a17d042 SL |
354 | register struct dmfdevice *addr; |
355 | register struct tty *tp0; | |
b660f54f | 356 | int unit; |
9c95d9b6 | 357 | int overrun = 0; |
0840b085 | 358 | register struct uba_device *ui; |
7a17d042 | 359 | |
0840b085 MK |
360 | ui = dmfinfo[dmf]; |
361 | if (ui == 0 || ui->ui_alive == 0) | |
362 | return; | |
363 | addr = (struct dmfdevice *)ui->ui_addr; | |
b660f54f | 364 | tp0 = &dmf_tty[dmf * 8]; |
7a17d042 SL |
365 | /* |
366 | * Loop fetching characters from the silo for this | |
367 | * dmf until there are no more in the silo. | |
368 | */ | |
369 | while ((c = addr->dmfrbuf) < 0) { | |
b660f54f JB |
370 | |
371 | unit = (c >> 8) & 07; | |
372 | tp = tp0 + unit; | |
7a17d042 | 373 | if (c & DMF_DSC) { |
b660f54f | 374 | addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; |
9c95d9b6 MK |
375 | if (addr->dmfrms & DMF_CAR) |
376 | (void)(*linesw[tp->t_line].l_modem)(tp, 1); | |
0840b085 | 377 | else if ((dmfsoftCAR[dmf] & (1 << unit)) == 0 && |
9c95d9b6 MK |
378 | (*linesw[tp->t_line].l_modem)(tp, 0) == 0) { |
379 | addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; | |
380 | addr->dmflctms = DMFLCR_ENA; | |
7a17d042 SL |
381 | } |
382 | continue; | |
383 | } | |
0840b085 | 384 | if ((tp->t_state&TS_ISOPEN) == 0) { |
9c95d9b6 MK |
385 | wakeup((caddr_t)&tp->t_rawq); |
386 | #ifdef PORTSELECTOR | |
0840b085 | 387 | if ((tp->t_state & TS_WOPEN) == 0) |
9c95d9b6 MK |
388 | #endif |
389 | continue; | |
7a17d042 | 390 | } |
223428e7 | 391 | if (c & (DMF_PE|DMF_DO|DMF_FE)) { |
b660f54f | 392 | if (c & DMF_PE) |
0840b085 MK |
393 | if ((tp->t_flags & (EVENP|ODDP)) == EVENP |
394 | || (tp->t_flags & (EVENP|ODDP)) == ODDP) | |
b660f54f JB |
395 | continue; |
396 | if ((c & DMF_DO) && overrun == 0) { | |
283ffc90 | 397 | log(LOG_WARNING, "dmf%d: silo overflow\n", dmf); |
b660f54f JB |
398 | overrun = 1; |
399 | } | |
400 | if (c & DMF_FE) | |
401 | /* | |
402 | * At framing error (break) generate | |
403 | * a null (in raw mode, for getty), or a | |
404 | * interrupt (in cooked/cbreak mode). | |
405 | */ | |
0840b085 | 406 | if (tp->t_flags & RAW) |
b660f54f JB |
407 | c = 0; |
408 | else | |
409 | c = tp->t_intrc; | |
7a17d042 | 410 | } |
7a17d042 SL |
411 | #if NBK > 0 |
412 | if (tp->t_line == NETLDISC) { | |
413 | c &= 0177; | |
414 | BKINPUT(c, tp); | |
415 | } else | |
416 | #endif | |
417 | (*linesw[tp->t_line].l_rint)(c, tp); | |
418 | } | |
419 | } | |
420 | ||
421 | /* | |
422 | * Ioctl for DMF32. | |
423 | */ | |
424 | /*ARGSUSED*/ | |
942f05a9 | 425 | dmfioctl(dev, cmd, data, flag) |
7a17d042 | 426 | dev_t dev; |
942f05a9 | 427 | caddr_t data; |
7a17d042 SL |
428 | { |
429 | register struct tty *tp; | |
430 | register int unit = minor(dev); | |
7da157da | 431 | int error; |
7a17d042 | 432 | |
0840b085 | 433 | if (unit & 0200) |
b660f54f | 434 | return (ENOTTY); |
7a17d042 | 435 | tp = &dmf_tty[unit]; |
7da157da BJ |
436 | error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); |
437 | if (error >= 0) | |
438 | return (error); | |
439 | error = ttioctl(tp, cmd, data, flag); | |
440 | if (error >= 0) { | |
21220e35 JB |
441 | if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS || |
442 | cmd == TIOCLBIC || cmd == TIOCLSET) | |
7a17d042 | 443 | dmfparam(unit); |
7da157da BJ |
444 | return (error); |
445 | } | |
446 | switch (cmd) { | |
7a17d042 SL |
447 | |
448 | case TIOCSBRK: | |
6e7edb25 | 449 | (void) dmfmctl(dev, DMF_BRK, DMBIS); |
7a17d042 | 450 | break; |
942f05a9 | 451 | |
7a17d042 | 452 | case TIOCCBRK: |
6e7edb25 | 453 | (void) dmfmctl(dev, DMF_BRK, DMBIC); |
7a17d042 | 454 | break; |
942f05a9 | 455 | |
7a17d042 | 456 | case TIOCSDTR: |
6e7edb25 | 457 | (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS); |
7a17d042 | 458 | break; |
942f05a9 | 459 | |
7a17d042 | 460 | case TIOCCDTR: |
6e7edb25 | 461 | (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC); |
7a17d042 | 462 | break; |
942f05a9 | 463 | |
7a17d042 | 464 | case TIOCMSET: |
6e7edb25 | 465 | (void) dmfmctl(dev, dmtodmf(*(int *)data), DMSET); |
7a17d042 | 466 | break; |
942f05a9 | 467 | |
7a17d042 | 468 | case TIOCMBIS: |
6e7edb25 | 469 | (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIS); |
7a17d042 | 470 | break; |
942f05a9 | 471 | |
7a17d042 | 472 | case TIOCMBIC: |
6e7edb25 | 473 | (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIC); |
7a17d042 | 474 | break; |
942f05a9 | 475 | |
7a17d042 | 476 | case TIOCMGET: |
942f05a9 | 477 | *(int *)data = dmftodm(dmfmctl(dev, 0, DMGET)); |
7a17d042 | 478 | break; |
942f05a9 | 479 | |
7a17d042 | 480 | default: |
7da157da | 481 | return (ENOTTY); |
7a17d042 | 482 | } |
7da157da | 483 | return (0); |
7a17d042 SL |
484 | } |
485 | ||
486 | dmtodmf(bits) | |
487 | register int bits; | |
488 | { | |
489 | register int b; | |
490 | ||
491 | b = bits & 012; | |
492 | if (bits & DML_ST) b |= DMF_RATE; | |
493 | if (bits & DML_RTS) b |= DMF_RTS; | |
494 | if (bits & DML_USR) b |= DMF_USRW; | |
495 | return(b); | |
496 | } | |
497 | ||
498 | dmftodm(bits) | |
499 | register int bits; | |
500 | { | |
501 | register int b; | |
502 | ||
503 | b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE; | |
504 | if (bits & DMF_USRR) b |= DML_USR; | |
505 | if (bits & DMF_RTS) b |= DML_RTS; | |
506 | return(b); | |
507 | } | |
508 | ||
509 | ||
510 | /* | |
511 | * Set parameters from open or stty into the DMF hardware | |
512 | * registers. | |
513 | */ | |
514 | dmfparam(unit) | |
515 | register int unit; | |
516 | { | |
517 | register struct tty *tp; | |
518 | register struct dmfdevice *addr; | |
519 | register int lpar, lcr; | |
520 | int s; | |
521 | ||
522 | tp = &dmf_tty[unit]; | |
523 | addr = (struct dmfdevice *)tp->t_addr; | |
524 | /* | |
525 | * Block interrupts so parameters will be set | |
526 | * before the line interrupts. | |
527 | */ | |
b660f54f | 528 | s = spltty(); |
7a17d042 SL |
529 | addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE; |
530 | if ((tp->t_ispeed)==0) { | |
c38b985f | 531 | tp->t_state |= TS_HUPCLS; |
6e7edb25 | 532 | (void) dmfmctl(unit, DMF_OFF, DMSET); |
9c95d9b6 | 533 | splx(s); |
7a17d042 SL |
534 | return; |
535 | } | |
536 | lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8); | |
537 | lcr = DMFLCR_ENA; | |
538 | if ((tp->t_ispeed) == B134) | |
539 | lpar |= BITS6|PENABLE; | |
fb01874e | 540 | else if (tp->t_flags & (RAW|LITOUT|PASS8)) |
7a17d042 SL |
541 | lpar |= BITS8; |
542 | else { | |
543 | lpar |= BITS7|PENABLE; | |
544 | /* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */ | |
545 | } | |
46245e68 SL |
546 | if (tp->t_flags&EVENP) |
547 | lpar |= EPAR; | |
7a17d042 SL |
548 | if ((tp->t_ospeed) == B110) |
549 | lpar |= TWOSB; | |
550 | lpar |= (unit&07); | |
551 | addr->dmflpr = lpar; | |
29eca3ca | 552 | addr->dmflctms = (addr->dmflctms &~ 0xff) | lcr; |
7a17d042 SL |
553 | splx(s); |
554 | } | |
555 | ||
556 | /* | |
557 | * DMF32 transmitter interrupt. | |
558 | * Restart the idle line. | |
559 | */ | |
560 | dmfxint(dmf) | |
561 | int dmf; | |
562 | { | |
0840b085 MK |
563 | int unit0 = dmf * 8; |
564 | struct tty *tp0 = &dmf_tty[unit0]; | |
7a17d042 SL |
565 | register struct tty *tp; |
566 | register struct dmfdevice *addr; | |
567 | register struct uba_device *ui; | |
b660f54f | 568 | register int t; |
7a17d042 | 569 | short cntr; |
7a17d042 SL |
570 | |
571 | ui = dmfinfo[dmf]; | |
572 | addr = (struct dmfdevice *)ui->ui_addr; | |
573 | while ((t = addr->dmfcsr) & DMF_TI) { | |
b660f54f | 574 | if (t & DMF_NXM) |
7a17d042 | 575 | /* SHOULD RESTART OR SOMETHING... */ |
b660f54f JB |
576 | printf("dmf%d: NXM line %d\n", dmf, t >> 8 & 7); |
577 | t = t >> 8 & 7; | |
578 | tp = tp0 + t; | |
579 | tp->t_state &= ~TS_BUSY; | |
c38b985f SL |
580 | if (tp->t_state&TS_FLUSH) |
581 | tp->t_state &= ~TS_FLUSH; | |
bed079ce MK |
582 | else if (dmf_dma[unit0 + t]) |
583 | ndflush(&tp->t_outq, (int)dmf_dma[unit0 + t]); | |
584 | dmf_dma[unit0 + t] = 0; | |
7a17d042 SL |
585 | if (tp->t_line) |
586 | (*linesw[tp->t_line].l_start)(tp); | |
587 | else | |
588 | dmfstart(tp); | |
589 | } | |
590 | } | |
591 | ||
592 | /* | |
593 | * Start (restart) transmission on the given DMF32 line. | |
594 | */ | |
595 | dmfstart(tp) | |
596 | register struct tty *tp; | |
597 | { | |
598 | register struct dmfdevice *addr; | |
bc3a8383 | 599 | register int unit, nch; |
7a17d042 | 600 | int s; |
b660f54f | 601 | register int dmf; |
7a17d042 SL |
602 | |
603 | unit = minor(tp->t_dev); | |
b660f54f | 604 | dmf = unit >> 3; |
7a17d042 SL |
605 | unit &= 07; |
606 | addr = (struct dmfdevice *)tp->t_addr; | |
607 | ||
608 | /* | |
609 | * Must hold interrupts in following code to prevent | |
610 | * state of the tp from changing. | |
611 | */ | |
b660f54f | 612 | s = spltty(); |
7a17d042 SL |
613 | /* |
614 | * If it's currently active, or delaying, no need to do anything. | |
615 | */ | |
c38b985f | 616 | if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) |
7a17d042 SL |
617 | goto out; |
618 | /* | |
619 | * If there are still characters in the silo, | |
620 | * just reenable the transmitter. | |
621 | */ | |
622 | addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; | |
623 | if (addr->dmftsc) { | |
624 | addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; | |
9c95d9b6 | 625 | addr->dmflctms = addr->dmflctms | DMF_TE; |
c38b985f | 626 | tp->t_state |= TS_BUSY; |
7a17d042 SL |
627 | goto out; |
628 | } | |
629 | /* | |
630 | * If there are sleepers, and output has drained below low | |
631 | * water mark, wake up the sleepers. | |
632 | */ | |
b660f54f JB |
633 | if (tp->t_outq.c_cc<=TTLOWAT(tp)) { |
634 | if (tp->t_state&TS_ASLEEP) { | |
635 | tp->t_state &= ~TS_ASLEEP; | |
636 | wakeup((caddr_t)&tp->t_outq); | |
637 | } | |
638 | if (tp->t_wsel) { | |
639 | selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); | |
640 | tp->t_wsel = 0; | |
641 | tp->t_state &= ~TS_WCOLL; | |
642 | } | |
7a17d042 SL |
643 | } |
644 | /* | |
645 | * Now restart transmission unless the output queue is | |
646 | * empty. | |
647 | */ | |
648 | if (tp->t_outq.c_cc == 0) | |
649 | goto out; | |
21a85e60 | 650 | if (tp->t_flags & (RAW|LITOUT)) |
7a17d042 SL |
651 | nch = ndqb(&tp->t_outq, 0); |
652 | else { | |
b660f54f JB |
653 | if ((nch = ndqb(&tp->t_outq, 0200)) == 0) { |
654 | /* | |
655 | * If first thing on queue is a delay process it. | |
656 | */ | |
7a17d042 SL |
657 | nch = getc(&tp->t_outq); |
658 | timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); | |
c38b985f | 659 | tp->t_state |= TS_TIMEOUT; |
7a17d042 SL |
660 | goto out; |
661 | } | |
662 | } | |
663 | /* | |
664 | * If characters to transmit, restart transmission. | |
665 | */ | |
b660f54f JB |
666 | if (nch >= dmf_mindma) { |
667 | register car; | |
668 | ||
bed079ce | 669 | dmf_dma[minor(tp->t_dev)] = nch; |
7a17d042 | 670 | addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; |
9c95d9b6 | 671 | addr->dmflctms = addr->dmflctms | DMF_TE; |
7a17d042 SL |
672 | car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum); |
673 | addr->dmfcsr = DMF_IE | DMFIR_TBA | unit; | |
674 | addr->dmftba = car; | |
b660f54f JB |
675 | addr->dmftcc = ((car >> 2) & 0xc000) | nch; |
676 | tp->t_state |= TS_BUSY; | |
677 | } else if (nch) { | |
7a17d042 SL |
678 | register char *cp = tp->t_outq.c_cf; |
679 | register int i; | |
680 | ||
b660f54f | 681 | dmf_dma[minor(tp->t_dev)] = 0; |
7a17d042 SL |
682 | nch = MIN(nch, DMF_SILOCNT); |
683 | addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; | |
9c95d9b6 | 684 | addr->dmflctms = addr->dmflctms | DMF_TE; |
7a17d042 SL |
685 | addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; |
686 | for (i = 0; i < nch; i++) | |
687 | addr->dmftbuf = *cp++; | |
688 | ndflush(&tp->t_outq, nch); | |
c38b985f | 689 | tp->t_state |= TS_BUSY; |
7a17d042 SL |
690 | } |
691 | out: | |
692 | splx(s); | |
693 | } | |
694 | ||
695 | /* | |
696 | * Stop output on a line, e.g. for ^S/^Q or output flush. | |
697 | */ | |
698 | /*ARGSUSED*/ | |
699 | dmfstop(tp, flag) | |
700 | register struct tty *tp; | |
701 | { | |
702 | register struct dmfdevice *addr; | |
b660f54f JB |
703 | register unit = minor(tp->t_dev) & 7; |
704 | int s; | |
7a17d042 SL |
705 | |
706 | addr = (struct dmfdevice *)tp->t_addr; | |
707 | /* | |
708 | * Block input/output interrupts while messing with state. | |
709 | */ | |
b660f54f JB |
710 | s = spltty(); |
711 | if (flag) { | |
712 | addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; | |
713 | if (addr->dmftsc) { | |
714 | /* | |
715 | * Flush regardless of whether we're transmitting | |
716 | * (TS_BUSY), if the silo contains untransmitted | |
717 | * characters. | |
718 | */ | |
719 | addr->dmfcsr = DMFIR_LCR | unit | DMF_IE; | |
9c95d9b6 | 720 | addr->dmflctms = addr->dmflctms | DMF_TE | DMF_FLUSH; |
b660f54f JB |
721 | /* this will interrupt so let dmfxint handle the rest */ |
722 | tp->t_state |= TS_FLUSH|TS_BUSY; | |
723 | } | |
724 | } else { | |
725 | if (tp->t_state & TS_BUSY) { | |
726 | /* | |
727 | * Stop transmission by disabling | |
728 | * the transmitter. We'll pick up where we | |
729 | * left off by reenabling in dmfstart. | |
730 | */ | |
731 | addr->dmfcsr = DMFIR_LCR | unit | DMF_IE; | |
9c95d9b6 | 732 | addr->dmflctms = addr->dmflctms &~ DMF_TE; |
b660f54f | 733 | /* no interrupt here */ |
c38b985f | 734 | tp->t_state &= ~TS_BUSY; |
b660f54f | 735 | } |
7a17d042 SL |
736 | } |
737 | splx(s); | |
738 | } | |
739 | ||
740 | /* | |
741 | * DMF32 modem control | |
742 | */ | |
743 | dmfmctl(dev, bits, how) | |
744 | dev_t dev; | |
745 | int bits, how; | |
746 | { | |
747 | register struct dmfdevice *dmfaddr; | |
748 | register int unit, mbits, lcr; | |
749 | int s; | |
750 | ||
751 | unit = minor(dev); | |
752 | dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr); | |
753 | unit &= 07; | |
b660f54f | 754 | s = spltty(); |
7a17d042 SL |
755 | dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; |
756 | mbits = dmfaddr->dmfrms << 8; | |
757 | dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit; | |
29eca3ca | 758 | lcr = dmfaddr->dmflctms; |
9c95d9b6 | 759 | mbits |= (lcr & 0xff00) >> 8; |
7a17d042 SL |
760 | switch (how) { |
761 | case DMSET: | |
9893b42d | 762 | mbits = (mbits &0xff00) | bits; |
7a17d042 SL |
763 | break; |
764 | ||
765 | case DMBIS: | |
766 | mbits |= bits; | |
767 | break; | |
768 | ||
769 | case DMBIC: | |
770 | mbits &= ~bits; | |
771 | break; | |
772 | ||
773 | case DMGET: | |
774 | (void) splx(s); | |
775 | return(mbits); | |
776 | } | |
7a17d042 SL |
777 | if (mbits & DMF_BRK) |
778 | lcr |= DMF_RBRK; | |
779 | else | |
780 | lcr &= ~DMF_RBRK; | |
9c95d9b6 | 781 | dmfaddr->dmflctms = ((mbits & 037) << 8) | (lcr & 0xff); |
7a17d042 SL |
782 | (void) splx(s); |
783 | return(mbits); | |
784 | } | |
785 | ||
786 | /* | |
787 | * Reset state of driver if UBA reset was necessary. | |
788 | * Reset the csr, lpr, and lcr registers on open lines, and | |
789 | * restart transmitters. | |
790 | */ | |
791 | dmfreset(uban) | |
792 | int uban; | |
793 | { | |
794 | register int dmf, unit; | |
795 | register struct tty *tp; | |
796 | register struct uba_device *ui; | |
797 | register struct dmfdevice *addr; | |
798 | int i; | |
799 | ||
7a17d042 SL |
800 | for (dmf = 0; dmf < NDMF; dmf++) { |
801 | ui = dmfinfo[dmf]; | |
802 | if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) | |
803 | continue; | |
804 | printf(" dmf%d", dmf); | |
27f8c1d5 | 805 | if (dmf_ubinfo[uban]) { |
9c95d9b6 MK |
806 | dmf_ubinfo[uban] = uballoc(uban, (caddr_t)cfree, |
807 | nclist*sizeof (struct cblock), 0); | |
27f8c1d5 | 808 | cbase[uban] = UBAI_ADDR(dmf_ubinfo[uban]); |
9c95d9b6 | 809 | } |
7a17d042 SL |
810 | addr = (struct dmfdevice *)ui->ui_addr; |
811 | addr->dmfcsr = DMF_IE; | |
b660f54f | 812 | addr->dmfrsp = dmf_timeout; |
7a17d042 SL |
813 | unit = dmf * 8; |
814 | for (i = 0; i < 8; i++) { | |
815 | tp = &dmf_tty[unit]; | |
c38b985f | 816 | if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { |
7a17d042 | 817 | dmfparam(unit); |
6e7edb25 | 818 | (void) dmfmctl(unit, DMF_ON, DMSET); |
c38b985f | 819 | tp->t_state &= ~TS_BUSY; |
7a17d042 SL |
820 | dmfstart(tp); |
821 | } | |
822 | unit++; | |
823 | } | |
824 | } | |
825 | } | |
826 | ||
0840b085 MK |
827 | /* |
828 | * dmflopen -- open the line printer port on a dmf32 | |
b660f54f | 829 | */ |
0840b085 MK |
830 | /* ARGSUSED */ |
831 | dmflopen(dev, flag) | |
832 | dev_t dev; | |
833 | int flag; | |
b660f54f JB |
834 | { |
835 | register int dmf; | |
836 | register struct dmfl_softc *sc; | |
837 | register struct uba_device *ui; | |
838 | register struct dmfdevice *addr; | |
839 | ||
0840b085 | 840 | dmf = DMFL_UNIT(dev); |
3c808bd7 MK |
841 | if (dmf >= NDMF || (ui = dmfinfo[dmf]) == 0 || ui->ui_alive == 0) |
842 | return (ENXIO); | |
843 | sc = &dmfl_softc[dmf]; | |
844 | if (sc->dmfl_state & OPEN) | |
845 | return (EBUSY); | |
b660f54f | 846 | addr = (struct dmfdevice *)ui->ui_addr; |
3c808bd7 MK |
847 | if (addr->dmfl_ctrl & DMFL_OFFLINE) { |
848 | #ifdef notdef | |
849 | log(LOG_WARNING, "dmf%d: line printer offline/jammed\n", | |
850 | dmf); | |
851 | #endif | |
0840b085 | 852 | return (EIO); |
b660f54f | 853 | } |
3c808bd7 MK |
854 | if ((addr->dmfl_ctrl & DMFL_CONV)) { |
855 | log(LOG_WARNING, "dmf%d: line printer disconnected\n", dmf); | |
0840b085 | 856 | return (EIO); |
b660f54f JB |
857 | } |
858 | ||
3c808bd7 | 859 | addr->dmfl_ctrl = 0; |
b660f54f | 860 | sc->dmfl_state |= OPEN; |
0840b085 | 861 | return (0); |
b660f54f JB |
862 | } |
863 | ||
0840b085 MK |
864 | /* ARGSUSED */ |
865 | dmflclose(dev, flag) | |
866 | dev_t dev; | |
867 | int flag; | |
b660f54f | 868 | { |
3c808bd7 | 869 | register int dmf = DMFL_UNIT(dev); |
b660f54f | 870 | register struct dmfl_softc *sc = &dmfl_softc[dmf]; |
3c808bd7 | 871 | register struct uba_device *ui = dmfinfo[dmf]; |
b660f54f | 872 | |
b660f54f | 873 | sc->dmfl_state = 0; |
0840b085 | 874 | if (sc->dmfl_info != 0) |
3c808bd7 | 875 | ubarelse((int)ui->ui_ubanum, &sc->dmfl_info); |
b660f54f | 876 | |
3c808bd7 | 877 | ((struct dmfdevice *)ui->ui_addr)->dmfl_ctrl = 0; |
b660f54f JB |
878 | } |
879 | ||
0840b085 MK |
880 | dmflwrite(dev, uio) |
881 | dev_t dev; | |
882 | struct uio *uio; | |
b660f54f | 883 | { |
8011f5df | 884 | register int n; |
b660f54f JB |
885 | register int error; |
886 | register struct dmfl_softc *sc; | |
887 | ||
888 | sc = &dmfl_softc[DMFL_UNIT(dev)]; | |
3c808bd7 MK |
889 | if (sc->dmfl_state & ERROR) |
890 | return (EIO); | |
891 | while (n = (unsigned)uio->uio_resid) { | |
892 | if (n > DMFL_BUFSIZ) { | |
893 | n = DMFL_BUFSIZ; | |
894 | sc->dmfl_state |= MOREIO; | |
895 | } else | |
896 | sc->dmfl_state &= ~MOREIO; | |
897 | if (error = uiomove(sc->dmfl_buf, (int)n, UIO_WRITE, uio)) | |
0840b085 | 898 | return (error); |
3c808bd7 | 899 | if (error = dmflout(dev, sc->dmfl_buf, n)) |
0840b085 | 900 | return (error); |
b660f54f | 901 | } |
0840b085 | 902 | return (0); |
b660f54f JB |
903 | } |
904 | ||
905 | ||
0840b085 MK |
906 | /* |
907 | * dmflout -- start io operation to dmf line printer | |
b660f54f JB |
908 | * cp is addr of buf of n chars to be sent. |
909 | * | |
910 | * -- dmf will be put in formatted output mode, this will | |
911 | * be selectable from an ioctl if the | |
912 | * need ever arises. | |
913 | */ | |
0840b085 MK |
914 | dmflout(dev, cp, n) |
915 | dev_t dev; | |
916 | char *cp; | |
917 | int n; | |
b660f54f JB |
918 | { |
919 | register struct dmfl_softc *sc; | |
920 | register int dmf; | |
921 | register struct uba_device *ui; | |
922 | register struct dmfdevice *d; | |
3c808bd7 | 923 | int s; |
b660f54f | 924 | |
0840b085 MK |
925 | dmf = DMFL_UNIT(dev); |
926 | sc = &dmfl_softc[dmf]; | |
927 | if (sc->dmfl_state & ERROR) | |
928 | return (EIO); | |
929 | ui = dmfinfo[dmf]; | |
930 | /* | |
931 | * allocate unibus resources, will be released when io | |
932 | * operation is done. | |
b660f54f | 933 | */ |
3c808bd7 MK |
934 | if (sc->dmfl_info == 0) |
935 | sc->dmfl_info = uballoc(ui->ui_ubanum, cp, n, 0); | |
0840b085 | 936 | d = (struct dmfdevice *)ui->ui_addr; |
3c808bd7 | 937 | d->dmfl_ctrl = sc->dmfl_format; /* indir reg 2 */ |
b660f54f JB |
938 | /* indir reg auto increments on r/w */ |
939 | /* SO DON'T CHANGE THE ORDER OF THIS CODE */ | |
3c808bd7 MK |
940 | d->dmfl_indrct = 0; /* prefix chars & num */ |
941 | d->dmfl_indrct = 0; /* suffix chars & num */ | |
942 | d->dmfl_indrct = sc->dmfl_info; /* dma lo 16 bits addr */ | |
943 | d->dmfl_indrct = -n; /* number of chars */ | |
944 | ||
945 | d->dmfl_indrct = ((sc->dmfl_info>>16)&3) | DMFL_OPTIONS; | |
946 | /* dma hi 2 bits addr */ | |
947 | d->dmfl_indrct = sc->dmfl_lines /* lines per page */ | |
948 | | (sc->dmfl_cols<<8); /* carriage width */ | |
b660f54f | 949 | sc->dmfl_state |= ASLP; |
3c808bd7 MK |
950 | s = spltty(); |
951 | d->dmfl_ctrl |= DMFL_PEN | DMFL_IE; | |
0840b085 | 952 | while (sc->dmfl_state & ASLP) { |
3c808bd7 | 953 | sleep(sc->dmfl_buf, PZERO + 8); |
0840b085 | 954 | while (sc->dmfl_state & ERROR) { |
3c808bd7 MK |
955 | timeout(dmflint, (caddr_t)dmf, 10 * hz); |
956 | sleep((caddr_t)&sc->dmfl_state, PZERO + 8); | |
b660f54f | 957 | } |
b660f54f | 958 | } |
3c808bd7 | 959 | splx(s); |
0840b085 | 960 | return (0); |
b660f54f | 961 | } |
b660f54f | 962 | |
0840b085 MK |
963 | /* |
964 | * dmflint -- handle an interrupt from the line printer part of the dmf32 | |
965 | */ | |
b660f54f | 966 | dmflint(dmf) |
0840b085 | 967 | int dmf; |
b660f54f | 968 | { |
b660f54f JB |
969 | register struct uba_device *ui; |
970 | register struct dmfl_softc *sc; | |
971 | register struct dmfdevice *d; | |
3c808bd7 | 972 | short dmfl_stats; |
b660f54f | 973 | |
0840b085 MK |
974 | ui = dmfinfo[dmf]; |
975 | sc = &dmfl_softc[dmf]; | |
976 | d = (struct dmfdevice *)ui->ui_addr; | |
b660f54f | 977 | |
3c808bd7 | 978 | d->dmfl_ctrl &= ~DMFL_IE; |
15ad1ce4 | 979 | dmfl_stats = d->dmfl_ctrl; |
0840b085 | 980 | if (sc->dmfl_state & ERROR) { |
3c808bd7 | 981 | if ((dmfl_stats & DMFL_OFFLINE) == 0) |
b660f54f | 982 | sc->dmfl_state &= ~ERROR; |
8011f5df | 983 | wakeup((caddr_t)&sc->dmfl_state); |
b660f54f JB |
984 | return; |
985 | } | |
3c808bd7 MK |
986 | if (dmfl_stats & DMFL_DMAERR) |
987 | log(LOG_WARNING, "dmf%d: NXM\n", dmf); | |
988 | if (dmfl_stats & DMFL_OFFLINE) { | |
989 | log(LOG_WARNING, "dmf%d: printer error\n", dmf); | |
b660f54f JB |
990 | sc->dmfl_state |= ERROR; |
991 | } | |
b660f54f | 992 | #ifdef notdef |
3c808bd7 MK |
993 | if (dmfl_stats & DMFL_PDONE) { |
994 | printf("bytes= %d\n", d->dmfl_indrct); | |
995 | printf("lines= %d\n", d->dmfl_indrct); | |
b660f54f | 996 | } |
3c808bd7 | 997 | #endif |
b660f54f | 998 | sc->dmfl_state &= ~ASLP; |
3c808bd7 MK |
999 | wakeup((caddr_t)sc->dmfl_buf); |
1000 | if (sc->dmfl_info && (sc->dmfl_state & MOREIO) == 0) | |
0840b085 | 1001 | ubarelse(ui->ui_ubanum, &sc->dmfl_info); |
b660f54f JB |
1002 | } |
1003 | ||
7a17d042 SL |
1004 | /* stubs for interrupt routines for devices not yet supported */ |
1005 | ||
0840b085 MK |
1006 | dmfsrint() |
1007 | { | |
1008 | printf("dmfsrint\n"); | |
1009 | } | |
7a17d042 | 1010 | |
0840b085 MK |
1011 | dmfsxint() |
1012 | { | |
1013 | printf("dmfsxint\n"); | |
1014 | } | |
7a17d042 | 1015 | |
0840b085 MK |
1016 | dmfdaint() |
1017 | { | |
1018 | printf("dmfdaint\n"); | |
1019 | } | |
b660f54f | 1020 | |
0840b085 MK |
1021 | dmfdbint() |
1022 | { | |
1023 | printf("dmfdbint\n"); | |
1024 | } | |
3c808bd7 | 1025 | #endif NDMF |