Mercurial > hg > Members > kono > nitros9-code
view level1/modules/printer.asm @ 1801:75f1d0fc33e1
A tip of the hat to the CoCoFEST has been added to sysgo
author | boisy |
---|---|
date | Wed, 13 Apr 2005 17:24:12 +0000 |
parents | 53c50c807d55 |
children |
line wrap: on
line source
******************************************************************** * Printer - CoCo Serial Printer Driver * * $Id$ * * Enhanced and re-written by Alan DeKok * * Problems with original: * returns wrong error on Read/SetStt * doesn't block output. The printer is a single-user device! * * Edt/Rev YYYY/MM/DD Modified by * Comment * ------------------------------------------------------------------ * 13 2003/01/05 Boisy G. Pitre * Back-ported to OS-9 Level Two. * * 2003/09/04 Boisy G. Pitre * Back-ported to OS-9 Level One. nam Printer ttl CoCo Serial Printer Driver ifp1 use defsfile endc tylg set Drivr+Objct atrv set ReEnt+Rev rev set $00 edition set 13 mod eom,name,tylg,atrv,Start,Size fcb READ.+WRITE. name fcs /Printer/ fcb edition one more revision level than the stock printer * Device memory area: offset from U org V.SCF V.SCF: free memory for driver to use V.PAR rmb 1 1=space, 2=mark parity V.BIT rmb 1 0=7, 1=8 bits V.STP rmb 1 0=1 stop bit, 1=2 stop bits V.COM rmb 2 Com Status baud/parity (=Y from SS.Comst Set/GetStt V.COL rmb 1 columns V.ROW rmb 1 rows V.WAIT rmb 2 wait count for baud rate? V.TRY rmb 2 number of re-tries if printer is busy V.RTRY rmb 1 low nibble of parity=high byte of number of retries V.BUFF rmb $80 room for 128 blocked processes size equ . * Baud Rate Delay Table BaudDly equ * IFEQ Level-1 * OS-9 Level One delay values (0.89MHz) fdb $0482 110 baud fdb $01A2 300 baud fdb $00CD 600 baud fdb $0063 1200 baud fdb $002D 2400 baud fdb $0013 4800 baud fdb $0005 9600 baud ELSE IFEQ H6309 * OS-9 Level Two delay values (1.78MHz) fdb $090C 110 baud fdb $034C 300 baud fdb $01A2 600 baud fdb $00CE 1200 baud fdb $0062 2400 baud fdb $002E 4800 baud fdb $0012 9600 baud fdb $0003 32000 baud ELSE * NitrOS-9 Level Two delay values (1.78MHz) fdb $090C 110 baud (Unchanged, unknown) fdb $03D0 300 baud fdb $01A2 600 baud (Unchanged, unknown) fdb $00F0 1200 baud fdb $0073 2400 baud fdb $0036 4800 baud fdb $0017 9600 baud fdb $0003 32000 baud (Unchanged, unknown) ENDC ENDC start equ * lbra Init lbra Read lbra Write lbra GetStt lbra SetStt * Term * * Entry: * U = address of device memory area * * Exit: * CC = carry set on error * B = error code * Term equ * clrb rts * Init * * Entry: * Y = address of device descriptor * U = address of device memory area * * Exit: * CC = carry set on error * B = error code * Init orcc #IntMasks ldx #PIA1Base clr $01,x ldd <IT.COL,y get number of columns/rows std <V.COL,u save it in statics lda #$FE sta ,x lda #$36 sta $01,x lda ,x andcc #^IntMasks ldd <IT.PAR,y parity and baud rate lbsr L0138 setup parity/baud in device memory lbsr L0104 get low bit of $FF22 into carry lbcs L0100 it's the ready flag * clear out buffer leax V.BUFF,u room for 128 blocked processes ldb #128 I010 clr ,x+ we're more concerned with room decb than with speed, so we don't use TFM bne I010 rts L005F ldb <PD.BAU,y get baud rate in path desc. andb #$0F keep lower nibble cmpb #$07 compare against highest lbhs Read aslb leax <BaudDly,pc table of delay times ldx b,x get delay counter stx <V.WAIT,u save it off clrb rts Bit_2 ldb #$02 L007D stb >PIA1Base L0080 pshs d ldd <V.WAIT,u get wait count for baud rate L0085 equ * IFNE H6309 decd count down by one ELSE subd #$0001 ENDC bne L0085 puls pc,d * Write * * Entry: * A = character to write * Y = address of path descriptor * U = address of device memory area * * Exit: * CC = carry set on error * B = error code * Write equ * leax V.BUFF,u point to the buffer ldb V.BUSY,u get my process number tst ,x get allowed process number bne W010 if not zero, else stb ,x I'm the only one allowed to use it W010 cmpb ,x am I allowed to use /p? beq W030 if yes, go write a character *************************************************************** * WARNING: If more than 128 processes try to use the printer, * this will CRASH BADLY. Since Level II on the Coco is limited * to 32 processes, I don't think it's a problem. *************************************************************** W020 tst ,x+ if not, find the first non-zero entry bne W020 stb -1,x and save my process number at the first zero pshs a lda V.BUFF,u process that's allowed to use /p sta V.BUSY,u make it the busy one ldb #S$Wake wake it up os9 F$Send send a signal to wake it IFNE H6309 tfr 0,x ELSE ldx #$0000 ENDC os9 F$Sleep and go to sleep forever puls a restore character to be sent, and continue W030 bsr L005F set up baud rate, etc in memory bcs L00CA pshs a bsr L00CB make sure that the device is ready puls a bcs L00CA if the device is not ready IFNE H6309 lde #$09 9 bits to send out ELSE pshs b,a lda #$09 sta 1,s puls a ENDC orcc #IntMasks turn off interrupts tst <V.BIT,u number of bits beq L00AC if 7 bits, count down by one IFNE H6309 dece initially send out start bit ELSE dec ,s ENDC L00AC bsr L007D write B to $FF20 and wait clrb lsra move A into carry rolb rolb IFNE H6309 dece count down on the number of bits to send ELSE dec ,s ENDC bne L00AC IFEQ H6309 puls b ENDC ldb <V.PAR,u space/mark parity beq L00BC 0=no parity andb #$FE 1=space, 0=mark parity * should be andb #$FD I think... bsr L007D dump out parity L00BC bsr Bit_2 and a stop bit tst <V.STP,u do another one? beq L00C9 bsr Bit_2 yes, dump out another stop bit L00C9 andcc #^IntMasks L00CA rts L0104 pshs b ldb >PIA1Base+$02 get a byte lsrb puls pc,b L00CB equ * IFNE H6309 clrd ELSE clra clrb ENDC std <V.TRY,u L00D0 ldd #$0303 L00D3 bsr L0104 get device ready status bcs L00DE if not ready, wait for a bit IFNE H6309 bsr L0080 wait ELSE lbsr L0080 wait ENDC decb bne L00D3 try again clrb rts L00DE lbsr L0080 wait for a while deca try 3 times, bne L00D3 pshs x ldx #$0001 os9 F$Sleep sleep for the rest of this tick puls x ldd <V.TRY,u IFNE H6309 incd we've tried once more and failed... ELSE addd #$0001 ENDC std <V.TRY,u ldb <V.RTRY,u number of retries to do beq L00D0 if unspecified, keep retrying cmpb <V.TRY,u if exceeded number of retries, bhi L00D0 then we crap out L0100 comb ldb #E$NotRdy rts * GetStat * * Entry: * A = function code * Y = address of path descriptor * U = address of device memory area * * Exit: * CC = carry set on error * B = error code * GetStt cmpa #SS.EOF end of file? bne L0112 clrb if so, exit with no error rts L0112 ldx PD.RGS,y cmpa #SS.ScSiz beq L0123 cmpa #SS.ComSt bne L0173 ldd <V.COM,u get Com status std R$Y,x clrb rts * get screen size GetStt L0123 clra ldb <V.COL,u std R$X,x ldb <V.ROW,u std R$Y,x clrb rts * SetStat * * Entry: * A = function code * Y = address of path descriptor * U = address of device memory area * * Exit: * CC = carry set on error * B = error code * SetStt cmpa #SS.ComSt bne Close if not, check if it's a close ldx PD.RGS,y ldd R$Y,x * A = Parity byte * B = baud rate L0138 std <V.COM,u save parity, baud rate in com status IFNE H6309 clrd ELSE clra clrb ENDC std <V.PAR,u sta <V.STP,u ldd <V.COM,u tstb bpl L014C inc <V.STP,u do 2 stop bits L014C bitb #$40 make sure the bit is zero bne Read bitb #$20 0=8, 1=7 bits beq L0157 inc <V.BIT,u L0157 bita #$20 beq L0169 if=0, no parity bita #$80 beq Read if high bit set (only for ACIA devices), error out inc <V.PAR,u parity bita #$40 bne L0169 1=space, inc <V.PAR,u 2=mark parity L0169 anda #$0F sta <V.RTRY,u rts Read comb ldb #E$BMode rts L0173 comb ldb #E$UnkSVc rts Close cmpa #SS.Close close the device? bne L0173 leax V.BUFF,u point to blocked process buffer C010 lda 1,x get next process number sta ,x+ bne C010 do until we have a zero byte lda V.BUFF,u get the first process in the queue beq C020 if none left ldb #S$Wake wake up signal os9 F$Send re-start the blocked process C020 clrb rts emod eom equ * end