/************************************************************
    Assembler-Ansteuerung des ATARI-Laserdruckers SLM 804
               Nach ST Computer 6/88 S. 56 ff.

          Autor:     Elmar Sonnenschein
          Version 1.01 | Stand 29.12.89 | Turbo C/MAS
************************************************************/


DMA_STATUS  equ   0xFFFF8604    /* DMA-Statusregister   */
MFP_GPIO    equ   0xFFFFFA01    /* I/0-Register des MFP */

/************************************************************
 -----------------------------------------------------------
 |||||||||||||||||||  PROGRAMMKODE  ||||||||||||||||||||||||
 -----------------------------------------------------------
************************************************************/

   ;*******************************
   ;* Subroutinen fr DMA-Zugriff *
   ;*******************************

   schreiben:                       ;Schreib-Daten in D0
               swap     D0          ;vertauschen wg. Langwert-bertragung
               move     #0x8A, D0   ;Takt (A0 auf high)
               move.l   D0, (A0)    ;schreiben
               bsr      warte40
               ;
   irqwarten:  moveq    #80, D1     ;400 ms
               bra      readywait
               ;
   lesen:      bsr      irqwarten
               bne      fehler
               move     #0x8A, 2(A0);Nchstes Byte
               move     (A0), D0    ;Daten holen
               and      #0x00FF, D0 ;nur Bytewert
               bsr      warte40
   fertig:     moveq    #0, D1      ;alles OK
   fehler:     rts
               ;
   warte40:    moveq    #44, D1     ;Delay 45 mal
   w40l:       dbf      D1, w40l
               rts
               ;
   readywait:  add.l    0x4BA, D1   ;Anzahl 200 Hz-Interrupts addieren
   rwloop:     btst.b   #5,MFP_GPIO ;Schon IRQ?
               beq      fertig      ;Ja
               cmp.l    0x4BA, D1   ;Schon Timeout?
               bge      rwloop      ;nein
               moveq    #-1, D1     ;Fehlerkode
               rts


/*******************************************************************
Ausdruck einer Seite auf dem Atari-Laserdrucker
*******************************************************************/

            /* int slm_print(int nr, char *saddr, int zlength) */

GLOBL slm_print
   saddr    = A1
   nr       = D3
   zlength  = D4     ;Zeilenlnge in Bytes
   slength  = D5     ;Streifenlnge  "
   cnt      = D6
TEXT
slm_print:     movem.l  D3-D6, -(SP)      ;Register retten
               move.l   A0, saddr         ;bergabeparameter retten
               move     D0, nr
               move     D1, zlength
               ;
               clr.l    -(SP)             ;User- als Supervisor-Stack
               move     #32, -(SP)        ;Funktionsnummer SUPER
               trap     #1                ;GEMDOS
               addq.l   #6, SP            ;Korrektur
               move.l   D0, old_ssp       ;alten SSP sichern
               ;
               tst.b    $43E              ;DMA in Gebrauch?
               bne      dma_benp          ;Ja, dann zurck
               st       $43E              ;Nein, dann DMA sperren
               ;
               pea      k_aus             ;Tastatur aus
               clr.w    -(SP)             ;Dummy
               move     #$19, -(SP)       ;Ikbdws-Kode
               trap     #$E               ;XBIOS
               addq.l   #8, A7            ;Stackkorrektur
               ;
               move     #33, cnt          ;34 Streifen fr DBF
               move     zlength, slength  ;slength = zlength * 100
               mulu     #100, slength     ;=> pro Streifen 100 Zeilen
               ;
               lea      DMA_STATUS, A0
               move     #$88,2(A0)        ;Controllerregister selektieren
               move     nr, D0
               lsl      #5, D0            ;in die richtige Position
               ori      #$A, D0           ;Print-Befehl
               bsr      schreiben         ;an Controller
               bne      prtrerror         ;bertragungsfehler?
               moveq    #3, D2            ;4 fr DBF
   prbef:      moveq    #0, D0            ;Nullbytes
               bsr      schreiben
               bne      prtrerror
               dbf      D2, prbef
               ;
               move.l   #$82, (A0)     ;letztes Befehlsbyte und Befehlsregister
                                       ;gleichzeitig => Druckstart (longwert!)
               add.l    #32,slength    ;Streifenlnge + 32 Byte FIFO
               move     SR, -(SP)      ;Status merken
               ori      #$700, SR      ;Interrupts sperren
               move.l   saddr, D0      ;Grafikdatenbasis
               moveq    #30, D1        ;DMA-FIFO 32 Bytes - Laser-FIFO 2 Bytes
   neustr:     move.l   D0,-(SP)
               bsr      setdma         ;DMA-Adresse setzen
               addq.l   #4, A7
               move     #$092, 2(A0)   ;DMA-Status lschen
               move     #$192, 2(A0)   ;Sektorzhler selektieren
               move.l   #$7F0112,(A0)  ;DMA-Count setzen
               ;
               add.l    slength, D0    ;Ende des Streifens
   strwart:    btst.b   #5,MFP_GPIO    ;Fehler?
               beq      dr_fehler
               ;
               movep    7(A0), D2      ;Aktuelle Adresse mit der
               cmp      D2, D0         ;Zieladresse vergleichen
               bne      strwart        ;weiter warten
               ;
               sub.l    D1, D0         ;FIFO-Offset abziehen
               ;
               moveq    #32, D1        ;ab jetzt LD-FIFO nicht benutzen
               cmp      #1, cnt        ;letzter Streifen erreicht
               bne      pr_over        ;nein
               move.l   zlength, slength
               mulu     #86, slength   ;Ja, dann die restlichen
               add.l    #32, slength   ;Zeilen (86) bertragen
   pr_over:    dbf      cnt, neustr    ;bis zum Seitenende
               ;
               move     (SP)+, SR      ;Interrupts freigeben
               move.l   #10*200, D1    ;10 s Timeout
               bsr      readywait
               bne      prtrerror
   dr_fertig:  bsr      lesen          ;Status auslesen
               bmi      prtrerror      ;Fehler
               move     D0, ret        ;Rckgabewert setzen
               ;
   prfertig:   move     #$80, 2(A0)    ;DMA fr Floppy freigeben
               sf       $43E           ;DMA freigeben
               bra      endp
               ;
   dr_fehler:  move     (SP)+, SR      ;Interrupts freigeben
               bra      dr_fertig
               ;
   prtrerror:  moveq    #-1, D0        ;bertragungsfehler aufgetreten
               bra      prfertig
               ;
   dma_benp:   moveq    #-3, D0        ;DMA benutzt: Fehlerkode -3
               bra      endp
               ;
               ;*** DMA-Adressen setzen ***
               ;
   setdma:     move.b   7(SP), 9(A0)
               move.b   6(SP), 7(A0)
               move.b   5(SP), 5(A0)
               rts
               ;
   endp:       pea      k_ein          ;Tastatur wieder ein
               clr.w    -(A7)          ;Dummy
               move     #$19,-(A7)     ;Ikbdws-Kode
               trap     #$E            ;XBIOS
               addq.l   #8, A7         ;Stackkorrektur
               ;
               moveq    #10, D1        ;50 ms warten, um dem
               add.l    $4BA, D1       ;Tastaturprozessor Gelegenheit
   delay:      cmp.l    $4BA, D1       ;zu geben, sich zu 'erholen'
               bge      delay          ;noch nicht zu Ende
               move.l   old_ssp, -(SP)
               move     #32, -(SP)
               trap     #1             ;wieder User-Modus
               addq.l   #6, SP
               movem.l  (A7)+, D3-D6
               move     ret, D0
               rts


/************************************************************
Sucht auf dem DMA-Bus nach dem Laserdrucker
************************************************************/

               /* int suche_slm(void) */
               /* Rckgabe: Devicenummer oder -2 = nicht gefunden */

GLOBL suche_slm
TEXT
suche_slm:     movem.l  D3-D6, -(SP)
               clr.l    -(SP)             ;User- als Supervisor-Stack
               move     #32, -(SP)        ;Funktionsnummer SUPER
               trap     #1                ;GEMDOS
               addq.l   #6, SP            ;Korrektur
               move.l   D0, old_ssp       ;alten SSP sichern
               ;
               tst.b    0x43E
               bne      dma_ben
               st       0x43E
               ;
               moveq    #7, D3      ;erste Devicenummer 7
               lea      DMA_STATUS, A0
   gersu:      lea      ldtext, A1
               move     #0x198,2(A0);DMA selektieren
               move     #0x88,2(A0) ;Controllerregister
               move     D3, D0      ;kopieren
               asl      #5, D0      ;nach Bit 5-7
               ori      #0x12, D0   ;Inquiry-Befehl
               bsr      schreiben   ;1.Byte der Befehlssequenz
               bmi      keindev     ;kein Gert vorhanden (Timeout)
               ;
               moveq    #3, D2      ;Sequenz mit Nullbytes auffllen
   subef:      moveq    #0, D0
               bsr      schreiben
               bmi      sutrerror   ;Timeout?
               dbf      D6, subef
               ;
               moveq    #-128, D0   ;6. Byte der Sequenz
               bsr      schreiben
               bmi      sutrerror
               ;
               bsr      lesen       ;Statusbyte lesen
               bmi      sutrerror
               tst.b    D0          ;Rckgabe testen
               bne      keindev     ;bertragungsfehler
               bsr      lesen       ;Gertetyp lesen
               bmi      sutrerror
               cmpi.b   #2, D0      ;Drucker?
               bne      dma_end     ;Nein, bertragung beenden
               moveq    #3, D2      ;Ja, dann 3 Bytes
   sules:      bsr      lesen       ;'berlesen'
               bmi      sutrerror
               dbf      D2, sules
               ;
               subq     #1, D0      ;letztes gelesenes Byte = Stringlnge
               cmpi.b   #21, D0     ;mindestens 21 Zeichen
               blt      dma_end     ;Nein, bertragung beenden
               moveq    #19, D2     ;20 Zeichen vergleichen
   kennloop:   bsr      lesen       ;Byte einlesen
               bmi      sutrerror
               cmp.b    (A1)+, D0   ;mit String vergleichen
               bne      dma_end     ;nicht identisch
               dbf      D2, kennloop
               ;
               move     D3, D0      ;Devicenummer zurckgeben
               move     #0x88,2(A0) ;neuer Befehl
               asl      #5, D3      ;nach Bit 5-7
               ori      #0x12, D3   ;Inquiry-Befehl
               moveq    #80, D2
   test:       bsr      warte40
               dbf      D2, test
               move     D3, (A0)    ;Schaltet Controller vom DMA-Bus
               bra      sufertig
               ;
   dma_end:    move     #0x88,2(A0) ;neuer Befehl
               move     D3, D0      ;kopieren
               asl      #5, D0      ;Bit 5-7
               ori      #0x12, D0   ;Inquiry
               bsr      warte40
               move     D0, (A0)    ;Schaltet Controller vom DMA-Bus
               bsr      warte40     ;Verzgerung
               ;
   keindev:    dbf      D3, gersu   ;nchste Devicenummer oder Schlu
               moveq    #-2, D0     ;nicht vorhanden
   sufertig:   move     #0x80,2(A0) ;DMA fr Floppy freigeben
               sf       0x43E       ;VBlanc zulassen
               bra      end
               ;
   sutrerror:  moveq    #-1, D0     ;bertragungsfehler
               bra      sufertig    ;abbrechen
               ;


/************************************************************
Laserdruckerparameter abfragen
************************************************************/

         /* int slm_msense(int nr, int anz, int def, char *addr) */

GLOBL slm_msense
   addr  = A1
   nr    = D4
   anz   = D5
   def   = D6
TEXT
slm_msense:    movem.l  D3-D6, -(SP)
               move.l   A0, addr          ;bergabeparameter
               move     D0, nr            ;retten
               move     D1, anz
               move     D2, def
               ;
               clr.l    -(SP)             ;User- als Supervisor-Stack
               move     #32, -(SP)        ;Funktionsnummer SUPER
               trap     #1                ;GEMDOS
               addq.l   #6, SP            ;Korrektur
               move.l   D0, old_ssp       ;alten SSP sichern
               ;
               tst.b    0x43E
               bne      dma_ben
               st       0x43E
               ;
               lea      DMA_STATUS, A0
               move     #0x198,2(A0);DMA selektieren
               move     #0x88,2(A0) ;Controllerregister
               move     nr, D0      ;Devicenummer holen
               asl      #5, D0      ;Bit 5-7
               ori      #0x1A, D0   ;Mode Sense-Befehl
               bsr      schreiben
               bmi      mstrerror
               moveq    #2, D2
   ssbef:      moveq    #0, D0      ;3 Nullbytes
               bsr      schreiben
               bmi      mstrerror
               dbf      D2, ssbef
               ;
               move     anz, D0     ;Anzahl der Werte
               bsr      schreiben
               bmi      mstrerror
               move     def, D0     ;Aktuelle oder Maximalwerte
               bsr      schreiben
               bmi      mstrerror
               bsr      lesen       ;Statusbyte lesen
               bmi      mstrerror
               move     D0, D3      ;Rckgabe retten
               bsr      lesen       ;Listenlnge lesen
               bmi      mstrerror
               move.b   D0, (addr)+ ;an Pufferanfang schreiben
               moveq    #0, D2      ;lschen
               move.b   D0, D2      ;kopieren
               subq.w   #1, D2      ;an DBF anpassen
   listloop:   bsr      lesen       ;Daten einlesen
               bmi      mstrerror
               move.b   D0, (addr)+ ;und in Puffer schreiben
               dbf      D2, listloop
               ;
               move     D3, D0      ;Rckgabewert
   msfertig:   move     #0x80,2(A0) ;DMA fr Floppy freigeben
               sf       0x43E       ;VBlanc zulassen
               bra      end
               ;
   mstrerror:  moveq    #-1, D0     ;bertragungsfehler
               bra      msfertig    ;abbrechen
               ;


/************************************************************
Laserdruckerparameter setzen
************************************************************/

         /* int slm_mselect(int nr, int anz, int def, char *addr) */

GLOBL slm_mselect
   addr  = A1
   nr    = D4
   anz   = D5
   def   = D6
TEXT
slm_mselect:   movem.l  D3-D6, -(SP)
               move.l   A0, addr          ;bergabeparameter
               move     D0, nr            ;retten
               move     D1, anz
               move     D2, def
               ;
               clr.l    -(SP)             ;User- als Supervisor-Stack
               move     #32, -(SP)        ;Funktionsnummer SUPER
               trap     #1                ;GEMDOS
               addq.l   #6, SP            ;Korrektur
               move.l   D0, old_ssp       ;alten SSP sichern
               ;
               tst.b    0x43E
               bne      dma_ben
               st       0x43E
               ;
               lea      DMA_STATUS, A0
               move     #0x198,2(A0);DMA selektieren
               move     #0x88,2(A0) ;Controllerregister
               move     nr, D0      ;Devicenummer holen
               asl      #5, D0      ;Bit 5-7
               ori      #0x15, D0   ;Mode Select-Befehl
               bsr      schreiben
               bmi      mstrerror
               moveq    #3, D2
   slbef:      moveq    #0, D0      ;4 Nullbytes
               bsr      schreiben
               bmi      mstrerror
               dbf      D2, slbef
               ;
               move     def, D0     ;0x80 => Defaultwerte einstellen
               bsr      schreiben
               bmi      mstrerror
               tst      def         ;Defaultwerte ?
               bne      mselfertig  ;Ja, dann Schlu
               ;
   listlp:     move.b   (addr)+, D0 ;Listenbytes holen
               bsr      schreiben
               bmi      mstrerror
               dbf      anz, listlp
               ;
   mselfertig: bsr      lesen       ;Statusbyte
               bmi      mstrerror
               move     #0x80,2(A0) ;DMA fr Floppy freigeben
               sf       0x43E       ;VBlanc zulassen
               bra      end
               ;


/************************************************************
Laserdrucker-Status abfragen
************************************************************/

               /* int slm_status(int nr) */

GLOBL slm_status
   nr    = D3
TEXT
slm_status:    movem.l  D3-D6, -(SP)
               move     D0, nr            ;bergabeparameter retten
               ;
               clr.l    -(SP)             ;User- als Supervisor-Stack
               move     #32, -(SP)        ;Funktionsnummer SUPER
               trap     #1                ;GEMDOS
               addq.l   #6, SP            ;Korrektur
               move.l   D0, old_ssp       ;alten SSP sichern
               ;
               tst.b    0x43E
               bne      dma_ben
               st       0x43E
               ;
               lea      DMA_STATUS, A0
               move     #0x198,2(A0)      ;DMA selektieren
               move     #0x88,2(A0)       ;Controllerregister
               move     nr, D0            ;Devicenummer holen
               asl      #5, D0            ;Bit 5-7
               ori      #0x3, D0          ;Request Sense-Befehl
               bsr      schreiben
               bmi      rqtrerror
               moveq    #4, D2
   rqbef:      moveq    #0, D0            ;5 Nullbytes
               bsr      schreiben
               bmi      rqtrerror
               dbf      D2, rqbef
               ;
               bsr      lesen             ;Statusbyte lesen
               bmi      rqtrerror         ;bertragungsfehler
   rqfertig:   move     #0x80,2(A0)       ;DMA fr Floppy freigeben
               sf       0x43E             ;VBlanc zulassen
               and      #0x00FF, D0       ;Status positiv
               bra      end
               ;
   rqtrerror:  moveq    #-1, D0           ;bertragungsfehler
               bra      rqfertig          ;abbrechen
               ;


/*******************************************************************
Standardende der Routinen (bis auf slm_print)
*******************************************************************/

   dma_ben:    moveq    #-3, D0           ;DMA benutzt: Fehlerkode -3
               ;
   end:        move     D0, ret           ;Rckgabewert setzen
               move.l   old_ssp, -(SP)
               move     #32, -(SP)
               trap     #1                ;wieder User-Modus
               addq.l   #6, SP
               movem.l  (A7)+, D3-D6
               move     ret, D0
               rts


/*******************************************************************
Daten
*******************************************************************/

DATA
   k_aus:      dc.b    $13             ;PAUSE-Kode Tastaturprozessor
   k_ein:      dc.b    $11             ;RESUME-Kode  "
   ldtext:     dc.b     "PAGE PRINTER:SLMC804"

BSS
   old_ssp:    ds.l    1               ;USP im Supervisormodus
   ret:        ds.w    1               ;Rckgabewert zwischenspeichern

