/* * (C) Copyright 1992, ..., 2004 the "DOSEMU-Development-Team". * * for details see file COPYING in the DOSEMU distribution */ /* for the Linux dos emulator versions 0.49 and newer * */ #define LPT_C 1 #include #include #include #include #include #include #include #include #include #include "emu.h" #include "timers.h" #include "lpt.h" #include "utilities.h" #include "dos2linux.h" static int stub_printer_write(int, int); struct p_fops def_pfops = { printer_open, stub_printer_write, printer_flush, printer_close, printer_write }; static struct printer lpt[NUM_PRINTERS] = { {NULL, "lpr", "", 5, 0x378}, {NULL, "lpr", "", 5, 0x278}, {NULL, NULL, NULL, 10, 0x3bc} }; int int17(void) { int num; if (LWORD(edx) + 1 > config.num_lpt) { p_printf("LPT: print to non-defined printer LPT%d\n", LWORD(edx) + 1); CARRY; return 1; } reset_idle(); switch (HI(ax)) { case 0: /* write char */ /* p_printf("print character on lpt%d : %c (%d)\n", LO(dx), LO(ax), LO(ax)); */ HI(ax) = printer_write(LO(dx), LO(ax)); break; case 1: /* init */ HI(ax) = LPT_NOTBUSY | LPT_ACK | LPT_ONLINE; num = LWORD(edx); p_printf("LPT: init printer %d\n", num); break; case 2: /* get status */ HI(ax) = LPT_NOTBUSY | LPT_ONLINE; /* dbug_printf("printer 0x%x status: 0x%x\n", LO(dx), HI(ax)); */ break; default: error("printer int17 bad call ax=0x%x\n", LWORD(eax)); show_regs(__FILE__, __LINE__); /* fatalerr = 8; */ break; } return 1; } int printer_open(int prnum) { int um; um = umask(026); if (lpt[prnum].file == NULL) { if (!lpt[prnum].dev) { lpt[prnum].file = tmpfile(); p_printf("LPT: opened tmpfile\n"); } else { lpt[prnum].file = fopen(lpt[prnum].dev, "a"); } } umask(um); p_printf("LPT: opened printer %d to %s, file %p\n", prnum, lpt[prnum].dev ? lpt[prnum].dev : "<>", (void *) lpt[prnum].file); return 0; } int printer_close(int prnum) { p_printf("LPT: closing printer %d, %s\n", prnum, lpt[prnum].dev ? lpt[prnum].dev : "<>"); if (lpt[prnum].file != NULL) fclose(lpt[prnum].file); lpt[prnum].file = NULL; /* delete any temporary files */ if (lpt[prnum].prtcmd && lpt[prnum].dev) { unlink(lpt[prnum].dev); free(lpt[prnum].dev); lpt[prnum].dev = NULL; } lpt[prnum].remaining = -1; return 0; } int printer_flush(int prnum) { p_printf("LPT: flushing printer %d\n", prnum); fflush(lpt[prnum].file); if (lpt[prnum].prtcmd) { size_t cmdbuflen, bufsize; FILE *pipe; char *buf, *cmdbuf; cmdbuflen = strlen(lpt[prnum].prtcmd) + 1 + strlen(lpt[prnum].prtopt) + 1; cmdbuf = malloc(cmdbuflen); if (!cmdbuf) { fprintf(stderr, "out of memory, giving up\n"); longjmp(NotJEnv, 0x4d); } strcpy(cmdbuf, lpt[prnum].prtcmd); strcat(cmdbuf, " "); strcat(cmdbuf, lpt[prnum].prtopt); p_printf("LPT: doing printer command ..%s..\n", cmdbuf); pipe = popen(cmdbuf, "w"); if (pipe == NULL) error("system(\"%s\") in lpt.c failed, cannot print!\ Command returned error %s\n", cmdbuf, strerror(errno)); free(cmdbuf); bufsize = ftell(lpt[prnum].file); buf = malloc(bufsize); if (!buf) { fprintf(stderr, "out of memory, giving up\n"); longjmp(NotJEnv, 0x4d); } fseek(lpt[prnum].file, 0, SEEK_SET); fread(buf, 1, bufsize, lpt[prnum].file); fwrite(buf, 1, bufsize, pipe); pclose(pipe); free(buf); fseek(lpt[prnum].file, 0, SEEK_SET); } /* mark not accessed */ lpt[prnum].remaining = -1; return 0; } int stub_printer_write(int prnum, int outchar) { printer_open(prnum); /* from now on, use real write */ lpt[prnum].fops.write = lpt[prnum].fops.realwrite; return printer_write(prnum, outchar); } int printer_write(int prnum, int outchar) { lpt[prnum].remaining = lpt[prnum].delay; fputc(outchar, lpt[prnum].file); return (LPT_NOTBUSY | LPT_ACK | LPT_ONLINE); } void printer_mem_setup(void) { int i; for (i = 0; i < 3; i++) { /* set the port address for each printer in bios */ *((u_short *)(0x408) + i) = lpt[i].base_port; } } /* DANG_BEGIN_FUNCTION printer_init * * description: * Initialize printer control structures * * DANG_END_FUNCTIONS */ void printer_init(void) { int i; for (i = 0; i < 3; i++) { p_printf("LPT: initializing printer %s\n", lpt[i].dev ? lpt[i].dev : "<>"); lpt[i].file = NULL; lpt[i].remaining = -1; /* mark not accessed yet */ lpt[i].fops = def_pfops; if (i >= config.num_lpt) lpt[i].base_port = 0; } } void close_all_printers(void) { int loop; for (loop = 0; loop < NUM_PRINTERS; loop++) { p_printf("LPT: closing printer %d (%s)\n", loop, lpt[loop].dev ? lpt[loop].dev : "<>"); printer_close(loop); } } int printer_tick(u_long secno) { int i; for (i = 0; i < NUM_PRINTERS; i++) { if (lpt[i].remaining >= 0) { p_printf("LPT: doing real tick for %d\n", i); if (lpt[i].remaining) { reset_idle(); lpt[i].remaining--; if (!lpt[i].remaining) printer_flush(i); } } } return 0; } void printer_config(int prnum, struct printer *pptr) { struct printer *destptr; if (prnum < NUM_PRINTERS) { destptr = &lpt[prnum]; destptr->prtcmd = pptr->prtcmd; destptr->prtopt = pptr->prtopt; destptr->dev = pptr->dev; destptr->file = pptr->file; destptr->remaining = pptr->remaining; destptr->delay = pptr->delay; } } void printer_print_config(int prnum, void (*print)(char *, ...)) { struct printer *pptr = &lpt[prnum]; (*print)("LPT%d command \"%s %s\" timeout %d device \"%s\" baseport 0x%03x\n", prnum+1, pptr->prtcmd, pptr->prtopt, pptr->delay, (pptr->dev ? pptr->dev : ""), pptr->base_port); } #undef LPT_C