home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 13 / AACD13.ISO / AACD / Utilities / ACDPlay / src / V1.5 / pickcdid / Quick.s < prev   
Text File  |  1997-04-26  |  27KB  |  657 lines

  1. *
  2. *   Quick.s V0.2 für PickCDID V0.4
  3. *
  4.  
  5.  include 'exec/ports.i'
  6.  include 'exec/memory.i'
  7.  include 'devices/scsidisk.i'
  8.  include 'devices/cd.i'
  9.  include 'dos/dos.i'
  10.  include 'dos/dosextens.i'
  11.  include 'intuition/intuition.i'
  12.  include 'libraries/gadtools.i'
  13.  include 'libraries/locale.i'
  14.  include 'lvo/dos.i'
  15.  include 'lvo/exec.i'
  16.  include 'lvo/intuition.i'
  17.  
  18.  include "CD-ROM.i"
  19.  
  20.  xref __wbflag
  21.  xref _DOSBase
  22.  xref _IntuitionBase
  23.  xref _ReqToolsBase
  24.  
  25. _LVOrtEZRequestA    equ -66
  26.  
  27. FALSE           equ 0
  28. TRUE            equ 1
  29. NULL            equ 0
  30.  
  31.  ;include "CD-ROM.s"
  32.  
  33.  
  34. **************************  ListLengthA  *****************************
  35. *
  36. *  ULONG ListLengthA(register __a0 struct List *list);
  37. *
  38.   CNOP 0,2
  39.   xdef _ListLengthA
  40. _ListLengthA:   movem.l d1/a0,-(sp)                 ; Register sichern
  41.                 moveq   #-2,d0                      ; Zähler auf -2 setzen
  42.  
  43. .Loop           addq.l  #1,d0                       ; Nodezähler erhöhen
  44.                 move.l  (a0),a0                     ; lh_Head/ln_Succ in a0
  45.                 move.l  a0,d1                       ; für Condition-Flags
  46.                 bne.s   .Loop                       ; bis Liste zu Ende ist
  47.  
  48. .EXIT           movem.l (sp)+,d1/a0                 ; Register restaurieren
  49.                 rts
  50.  
  51.  
  52. **************************  FormatA   ********************************
  53. *
  54. *  void FormatA(register __a0 char *buffer, register __a1 char *formatstr, ...);
  55. *
  56. * Kopiert den formatierten Text formatstr nach buffer und benutzt dabei
  57. * die Werte bzw. Adressen der Argumente vom Stack.
  58. *
  59.   CNOP 0,2
  60.   xdef _FormatA
  61. _FormatA:       movem.l d0-d1/a0-a3/a6,-(sp)        ; Register sichern
  62.                 movea.l 4.w,a6                      ; SysBase laden
  63.                                                     ; Argumente für RawDoFmt()
  64.                 movea.l a0,a3                       ; PutChData -> a3
  65.                 movea.l a1,a0                       ; FormatString -> a0
  66.                 movea.l a7,a1                       ; DataStream -> a1
  67.                 lea     32(a1),a1                   ; Offset da Register auf dem Stack sind
  68.                 lea     PutChProc(pc),a2            ; Copy-Routine
  69.                 jsr     _LVORawDoFmt(a6)
  70.  
  71. .EXIT           movem.l (sp)+,d0-d1/a0-a3/a6        ; Register restaurieren
  72.                 rts
  73.  
  74. PutChProc:      move.b  d0,(a3)+                    ; wird von RawDoFMt aufgerufen
  75.                 rts                                 ; soll ich einen Overflowtest einbauen?
  76.  
  77.  
  78. *************************  ShowMsgA   ********************************
  79. *
  80. *  void ShowMsgA(char *ReqTitle, char *ReqBody, ...);
  81. *
  82. * Zeigt eine Nachricht Abhängig von __wbflag auf der Workbench als Requester
  83. * oder im CLI an.
  84. *
  85.   CNOP 0,2
  86.   xdef _ShowMsgA
  87. _ShowMsgA:      movem.l d0-d2/a0-a4/a6,-(sp)
  88.  
  89.                 tst.w   __wbflag                    ; von WB gestartet?
  90.                 beq     .CLIMsg                     ; nein: in CLI schreiben
  91.  
  92. .WBMsg          move.l  _ReqToolsBase,d1            ; ReqToolsLib geöffnet?
  93.                 beq     .asl
  94.                 movea.l d1,a6                       ; ReqToolsBase laden
  95.                 suba.l  a0,a0                       ; taglist=NULL
  96.                 move.l  44(a7),a1                   ; ReqBody
  97.                 lea     Okay(pc),a2                 ; GadgetBody
  98.                 suba.l  a3,a3                       ; *reqInfo=NULL
  99.                 movea.l a7,a4                       ; * auf restliche
  100.                 adda.l  #48,a4                      ;  Argumente nach a4
  101.                 jsr     _LVOrtEZRequestA(a6)
  102.                 bra     .EXIT
  103.  
  104. .asl            lea     MsgEasyStruct(pc),a1        ; a1=*EasyStruct
  105.                 move.l  40(a7), es_Title(a1)        ; Titel eintragen
  106.                 move.l  44(a7), es_TextFormat(a1)   ; Text eintragen
  107.                 lea     Okay(pc),a0
  108.                 move.l  a0, es_GadgetFormat(a1)     ; Gadgettext eintragen
  109.                 suba.l  a0,a0                       ; *Window=NULL
  110.                 suba.l  a2,a2                       ; a2=NULL (IDCMP)
  111.                 movea.l a7,a3                       ; * auf restliche
  112.                 adda.l  #48,a3                      ;  Argumente nach a3
  113.                 move.l  _IntuitionBase, a6          ; IBase laden
  114.                 jsr     _LVOEasyRequestArgs(a6)     ; Requester darstellen
  115.                 bra     .EXIT                       ; das wars
  116.  
  117. .CLIMsg         suba.l  #88,a7                      ; 88 bytes auf´m Stack
  118.                 move.l  a7,d1                       ;  freimachen damit 87
  119.                 moveq   #87,d2                      ;  Zeichen da reinpassen
  120.                 move.l  _DOSBase, a6                ; DOSBase laden
  121.                 jsr     _LVOGetProgramName(a6)      ; ProgNamen in Puffer schreiben
  122.                 tst.w   d0                          ; geklappt ?
  123.                 beq     .WriteMsg                   ; nö: Msg ausgeben
  124.                  move.l  a7,d1
  125.                  jsr     _LVOPutStr(a6)             ; Prognamen ausgeben
  126.                  lea     Colon(pc),a1
  127.                  move.l  a1,d1
  128.                  jsr     _LVOPutStr(a6)             ; ": " ausgeben
  129.  
  130. .WriteMsg       adda.l  #88,a7                      ; Stack zurücksetzen
  131.                 move.l  44(a7),d1                   ; ReqBody als Arg für VPrintf
  132.                 move.l  a7,d2
  133.                 addi.b  #48,d2                      ; Rest als Argument
  134.                 jsr     _LVOVPrintf(a6)             ; Msg ausgeben
  135.                 lea     LineFeed(pc),a1             ; erst mit dem LF
  136.                 move.l  a1,d1                       ;  erscheint alles im
  137.                 jsr     _LVOPutStr(a6)              ;  CON-CLI-Window
  138.  
  139. .EXIT           movem.l (sp)+, d0-d2/a0-a4/a6       ; Register wiederherstellen
  140.                 rts
  141.  
  142. MsgEasyStruct:  dc.l 20             ; es_StructSize
  143.                 dc.l 0              ; es_Flags
  144.                 dc.l 0              ; es_Title
  145.                 dc.l 0              ; es_TextFormat
  146.                 dc.l 0              ; es_GadgetFormat
  147.  
  148. Okay:           dc.b "Okay",0
  149. Colon:          dc.b ": ",0
  150. LineFeed:       dc.b 10,0
  151.  
  152.  
  153. *************************  GetVecA  *********************************
  154. *
  155. *  APTR GetVecA(register __d0 ULONG bytesize, register __d1 ULONG requirements);
  156. *
  157. * Versucht 'bytesize' Bytes RAM zu erhalten und Zeigt im Fehlerfall eine
  158. * Fehlermeldung an.
  159. *
  160.   CNOP 0,2
  161.   xdef _GetVecA
  162. _GetVecA:       movem.l d1-d2/a0-a1/a6,-(sp)    ; alte Register speichern
  163.                 move.l  d0,d2                   ; bytesize für Fehlerfall sichern
  164.                 move.l  4.w,a6                  ; SysBase laden
  165.                 jsr     _LVOAllocVec(a6)        ; AllocVec bytesize requiements
  166.                 tst.l   d0                      ; erfolgreich?
  167.                 bne     .EXIT                   ; mem <> 0 -->.EXIT
  168.                 move.l  d2,-(a7)                ; Argumente für ShowMsgA
  169.                 lea     NoMem(pc),a0            ;  auf den Stack schieben
  170.                 move.l  a0,-(a7)
  171.                 lea     Error(pc),a0
  172.                 move.l  a0,-(a7)
  173.                 bsr     _ShowMsgA               ; Error anzeigen
  174.                 lea     12(a7),a7               ; Stack wieder runtersetzen
  175.  
  176. .EXIT           movem.l (sp)+,d1-d2/a0-a1/a6    ; alte Register restaurieren
  177.                 rts
  178.  
  179. Error:      dc.b "Error",0
  180. NoMem:      dc.b "Could not get %lU bytes of memory",0
  181.  
  182. ***********************  FlushMessagesA  *****************************
  183. *
  184. *  void FlushMessagesA(register __a0 struct MsgPort *port);
  185. *
  186. * Leert den MsgPort 'port', der auch NULL sein kann.
  187. *
  188.   CNOP 0,2
  189.   xdef _FlushMessagesA
  190. _FlushMessagesA:    movem.l d0-d2/a0-a1/a6,-(sp)
  191.                     move.l  a0,d2                   ; MsgPort sichern und testen
  192.                     beq     .EXIT
  193.                     move.l  4.w,a6                  ; SysBase laden
  194.  
  195. .loop               jsr     _LVOGetMsg(a6)          ; Msg holen
  196.                     tst.l   d0                      ; vorhanden?
  197.                     beq     .EXIT                   ; nein: Ende
  198.                     move.l  d0,a1
  199.                     jsr     _LVOReplyMsg(a6)        ; ja: antworten
  200.                     movea.l d2,a0                   ; MsgPort zurückholen
  201.                     bra     .loop                   ; nächste Msg holen
  202.  
  203. .EXIT               movem.l (sp)+,d0-d2/a0-a1/a6
  204.                     rts
  205.  
  206. *////*---------------- CDOpenDeviceA() ----------------------------< >-*/
  207. */
  208. *  struct CDxRequest *CDOpenDeviceA(register __a0 char *devicename, register __d0 ULONG unitnumber, register __d1 ULONG lun);
  209. *
  210. * Öffnet das übergebene SCSI-Device und gibt einen Zeiger auf eine
  211. * ausgefüllte CDx-Struktur zurück. Konnte das Device nicht geöffnet werden,
  212. * wird der Fehler angezeigt und die Funktion gibt NULL zurück.
  213. * Achtung: Der Devicename wird nicht kopiert, und muß für CDChangeDeviceA()
  214. *          unbedingt erhalten bleiben!
  215. *
  216.   CNOP 0,2
  217.   xdef _CDOpenDeviceA
  218. _CDOpenDeviceA: movem.l d1-d7/a0-a6,-(sp)
  219.                 move.l  4.w,a6                      ; a6 = SysBase
  220.  
  221.                 move.l  a0,a4                       ; a4 = devicename
  222.                 move.l  d0,d2                       ; d2 = unitnumber
  223.                 move.l  d1,d3                       ; d3 = lun
  224.  
  225.                 moveq   #0,d4
  226.  
  227. .GetCDxStruct   move.l  #cdx_SIZEOF+CDTOC_SIZEOF+AUDIOPAGE_SIZEOF,d0  ; Speicher für CDxRequest, cdx_TOCData
  228.                 move.l  #MEMF_PUBLIC|MEMF_CLEAR,d1  ;  und cdx_ValidAudioPage
  229.                 bsr     _GetVecA
  230.                 tst.l   d0
  231.                 beq     .EXIT
  232.                 move.l  d0,a3                       ; a3 = CDxRequest
  233.                 addi.l  #cdx_SIZEOF,d0
  234.                 move.l  d0,cdx_TOCData(a3)          ; alle Adressen eintragen
  235.                 addi.l  #CDTOC_SIZEOF,d0
  236.                 move.l  d0,cdx_ValidAudioPage(a3)
  237.  
  238. .InitCDxStruct  move.b  d2,cdx_Unit(a3)
  239.                 move.b  d3,cdx_LUN(a3)
  240.                 move.l  a4,cdx_DeviceName(a3)
  241.  
  242. .GetBufMem      move.l  #DATA_LEN+SENSE_LEN,d0      ; 2 Puffer-Blöcke
  243.                 move.l  #MEMF_PUBLIC|MEMF_24BITDMA|MEMF_CLEAR,d1
  244.                 bsr     _GetVecA
  245.                 move.l  d0,cdx_SCSIData(a3)         ; Data-Block
  246.                 beq     FreeCDxStruct
  247.                 addi.l  #DATA_LEN,d0                ; Sense-Block errechnen
  248.                 move.l  d0,cdx_SCSISense(a3)
  249.  
  250. .CreateIOPort   jsr     _LVOCreateMsgPort(a6)
  251.                 move.l  d0,cdx_IOPort(a3)
  252.                 bne     .CreateIOReq
  253.                  lea     NoPort(pc),a0              ;  auf den Stack schieben
  254.                  move.l  a0,-(a7)
  255.                  lea     Error(pc),a0
  256.                  move.l  a0,-(a7)
  257.                  bsr     _ShowMsgA                  ; Error anzeigen
  258.                  lea     8(a7),a7                   ; Stack wieder runtersetzen
  259.                  bra    FreeBufMem
  260.  
  261. .CreateIOReq    movea.l d0,a0
  262.                 moveq   #IOSTD_SIZE,d0
  263.                 jsr     _LVOCreateIORequest(a6)
  264.                 move.l  d0,cdx_IORequest(a3)
  265.                 beq     DeleteIOPort
  266.                 move.l  d0,a2                       ; a2 = cdx_IORequest
  267.  
  268. .OpenDevice     move.l  d3,d0
  269.                 mulu.w  #10,d0
  270.                 add.l   d2,d0                       ; d0 = unit + lun*10
  271.                 moveq   #0,d1                       ; Flags
  272.                 move.l  a4,a0                       ; devicename
  273.                 move.l  a2,a1                       ; io_request
  274.                 jsr     _LVOOpenDevice(a6)
  275.                 tst.l   d0
  276.                 beq     .GetCmdStruct
  277.                  move.l  d3,-(a7)                   ; Argumente für ShowMsgA
  278.                  move.l  d2,-(a7)
  279.                  move.l  a4,-(a7)
  280.                  lea     NoDevice(pc),a0            ;  auf den Stack schieben
  281.                  move.l  a0,-(a7)
  282.                  lea     Error(pc),a0
  283.                  move.l  a0,-(a7)
  284.                  bsr     _ShowMsgA                  ; Error anzeigen
  285.                  lea     20(a7),a7                  ; Stack wieder runtersetzen
  286.                  bra     DeleteIOReq
  287.  
  288. .GetCmdStruct   move.l  #scsi_SIZEOF,d0
  289.                 move.l  #MEMF_PUBLIC|MEMF_CLEAR,d1  ; RAM für die SCSICmd-
  290.                 bsr     _GetVecA                    ;  Struktur
  291.                 move.l  d0,cdx_Cmd(a3)
  292.                 beq     CloseDevice
  293.                 move.l  d0,a1                       ; a1 = SCSICmd
  294.  
  295.                 move.l  a3,a0
  296.                 bsr     _CDInitDeviceA              ; CDx Rest ausfüllen
  297.  
  298.                 move.l  a3,d0                       ; Return CDxRequest
  299. .EXIT           movem.l (sp)+,d1-d7/a0-a6
  300.                 rts
  301.  
  302. NoDevice:   dc.b    "Could not open SCSI device '%s' Unit %ld LUN %ld",0
  303. NoPort:     dc.b    'Failed to create message port',0
  304.  
  305.  
  306. ********************* CDInitDeviceA() *********************************
  307. *
  308. *  LONG CDInitDeviceA(register __a0 struct CDxRequest);
  309. *
  310. *
  311.   CNOP 0,2
  312. _CDInitDeviceA: movem.l d1-d7/a0-a6,-(sp)
  313.                 move.l  a0,a3                       ; a3 = cdx
  314.  
  315.                 move.l  cdx_IORequest(a0),a1
  316.                 move.w  #HD_SCSICMD,IO_COMMAND(a1)  ; IOStdRequest füllen
  317.                 move.l  cdx_Cmd(a0),IO_DATA(a1)
  318.                 move.l  #scsi_SIZEOF,IO_LENGTH(a1)
  319.  
  320. .DoInquiry      moveq   #6,d0
  321.                 moveq   #SCSIF_AUTOSENSE|SCSIF_READ,d1
  322.                 lea     CMDInquiry,a1
  323.                 bsr     CDDoSCSIA                   ; Inquiry schicken
  324.                 bne     .EXIT
  325.  
  326.                 move.l  cdx_SCSIData(a3),a2
  327.                 move.b  (a2),d0
  328.                 andi.l  #%00011111,d0               ; nur Bits 0-4
  329.                 move.b  d0,cdx_DeviceType(a3)       ; Peripheral Device Type
  330.  
  331.                 adda.l  #8,a2                       ; a2 = CDROM-VendorID
  332. .VendorUnknown  lea     UnknownVendor(pc),a0
  333.                 move.l  a0,cdx_Vendor(a3)
  334.                 move.l  (a2)+,(a0)+
  335.                 move.l  (a2),(a0)
  336.  
  337. .CopyRest       adda.l  #8,a2                       ; nächte Bytes der Inquirydaten
  338.                 lea     cdx_Product(a3),a0          ; Product Identification
  339.                 moveq   #3,d0                       ; 16 Bytes (4 Langworte)
  340. .l1             move.l  (a2)+,(a0)+                 ;  kopieren
  341.                 dbra    d0,.l1
  342.                 lea     cdx_Revision(a3),a0         ; Product Revision Level
  343.                 move.l  (a2)+,(a0)                  ; nur 4 Bytes groß
  344.                 lea     cdx_Specific(a3),a0         ; Vendor Specific
  345.                 moveq   #4,d0                       ; 20 Bytes (5 Langworte)
  346. .l2             move.l  (a2)+,(a0)+                 ;  kopieren
  347.                 dbra    d0,.l2
  348.  
  349. .FillCDx        move.b  #AUDIO_STAT_NO_DISK,cdx_AudioStatus(a3)
  350.                 move.b  #AUDIO_STAT_NO_DISK,cdx_Active(a3)
  351.                 move.l  a3,a0
  352.                 bsr     _CDUpdateA                  ; Rest der CDx-Struktur füllen
  353.                 bsr     _CDReadTOCA                 ; TOC einlesen
  354.  
  355. .EXIT           movem.l (sp)+,d1-d7/a0-a6
  356.                 rts
  357.  
  358. CMDInquiry:     dc.b    $12, 0, 0, 0, 96, 0
  359.  
  360.  
  361. *********************** CDCloseDeviceA() *****************************
  362. *
  363. *  BOOL CDCloseDeviceA(register __a0 struct CDxRequest);
  364. *
  365. * Schließt ein SCSI-Device, das mit CDOpenDeviceA() geöffnet wurde. Das
  366. * Ergebnis ist dabei immer NULL.
  367. *
  368.   CNOP 0,2
  369.   xdef _CDCloseDeviceA
  370. _CDCloseDeviceA: movem.l d1-d7/a0-a6,-(sp)
  371.                 move.l  4.w,a6
  372.                 move.l  a0,a3                       ; a3 = MyCDxReq
  373.  
  374. CloseCmdStruct  move.l  cdx_Cmd(a3),a1
  375.                 jsr     _LVOFreeVec(a6)
  376.  
  377. CloseDevice     move.l  cdx_IORequest(a3),a1
  378.                 jsr     _LVOCloseDevice(a6)
  379.  
  380. DeleteIOReq     move.l  cdx_IORequest(a3),a0
  381.                 jsr     _LVODeleteIORequest(a6)
  382.  
  383. DeleteIOPort    move.l  cdx_IOPort(a3),a0
  384.                 jsr     _LVODeleteMsgPort(a6)
  385.  
  386. FreeBufMem      move.l  cdx_SCSIData(a3),a1
  387.                 jsr     _LVOFreeVec(a6)
  388.  
  389. FreeCDxStruct   move.l  a3,a1
  390.                 jsr     _LVOFreeVec(a6)
  391.  
  392. .EXIT           moveq   #NULL,d0
  393.                 movem.l (sp)+,d1-d7/a0-a6
  394.                 rts
  395.  
  396.  
  397. ************************ CDDoSCSIA() *********************************
  398. *
  399. *  LONG CDDoSCSIA(register __a0 struct CDxRequest *cdx, a1 APTR Command, d0 cmdlen. d1 flags);
  400. *
  401. * Führt das übergebene SCSI Direktkommando aus und gibt im Fehlerfall einen
  402. * Wert zurück, der sich aus dem Sense Key (Bit 16-31), dem Additional Sense
  403. * Code (Bit 8-15) und dem Additional Sense Code Qualifier (Bit 0-7)
  404. * zusammensetzt. Ist keine CD eingelegt werden alle CD-abhängigen Daten auf
  405. * 0 gesetzt. Die Conditioncodes werden in Abhängigkeit von d0 gesetzt.
  406. *
  407.   CNOP 0,2
  408. CDDoSCSIA:      movem.l d1/a0-a2/a6,-(sp)
  409.                 move.l  4.w,a6                  ; SysBase...
  410.                 move.l  cdx_Cmd(a0),a2          ; a2=SCSICmd
  411.  
  412.                 move.l  cdx_SCSIData(a0),(a2)+  ; scsi_Data;
  413.                 move.l  #DATA_LEN,(a2)+         ; scsi_Length;
  414.                 clr.l   (a2)+                   ; scsi_Actual;
  415.                 move.l  a1,(a2)+                ; scsi_Command;
  416.                 move.w  d0,(a2)+                ; scsi_CmdLength;
  417.                 clr.w   (a2)+                   ; scsi_CmdActual;
  418.                 move.b  d1,(a2)+                ; scsi_Flags;
  419.                 clr.b   (a2)+                   ; scsi_Status;
  420.                 move.l  cdx_SCSISense(a0),(a2)+ ; scsi_SenseData;
  421.                 move.w  #SENSE_LEN,(a2)+        ; scsi_SenseLength;
  422.                 clr.w   (a2)                    ; scsi_SenseActual;
  423.  
  424.                 move.l  a0,a2                   ; CDxRequest retten
  425.  
  426.                 move.l  cdx_IORequest(a0),a1
  427.                 jsr     _LVODoIO(a6)            ; Kommando schicken und warten
  428.  
  429.                 moveq   #0,d0                   ; Return = 0
  430.                 move.l  cdx_Cmd(a2),a1          ; a1=SCSICmd
  431.                 tst.w   scsi_SenseActual(a1)    ; Sense Daten da?
  432.                 beq     .EXIT
  433.  
  434.                 move.l  scsi_SenseData(a1),a1   ; a1=SenseData
  435.                 move.b  (a1),d1                 ; Error Code ($70 oder $71)
  436.                 andi.b  #%01111111,d1           ; Valid-Bit auslassen
  437.                 cmp.b   #$70,d1                 ; Current Error ($70) ?
  438.                 bne     .EXIT
  439.                 move.b  2(a1),d0                ; d0=Sense Key
  440.                 andi.b  #%00001111,d0           ; nur 4 Bits
  441.                 tst.b   d0                      ; NO SENSE ($0) ?
  442.                 beq     .EXIT
  443.                 move.b  d0,cdx_SenseKey(a2)     ; in cdx schreiben (für ARexx)
  444.                 swap.w  d0                      ; Returnwert berechnen
  445.                 cmp.b   #6,7(a1)                ; ASC und ASCQ vorhanden?
  446.                 blt     .EXIT
  447.                 move.w  12(a1),d0               ; ASC und ASCQ zu Returnwert
  448.                 move.w  d0,cdx_AddSenseCode(a2) ; in cdx schreiben
  449.  
  450. .EXIT           movem.l (sp)+,d1/a0-a2/a6
  451.                 tst.l   d0                      ; Conditioncodes setzen
  452.                 rts
  453.  
  454.  
  455. ************************ CDUpdateA() **********************************
  456. *
  457. *  LONG CDUpdateA(register __a0 struct CDxRequest *cdx);
  458. *
  459. * Aktualisiert den Track, Index, Adresssen und Audiostatus der übergebenen
  460. * CDx-Struktur. Tritt ein Fehler auf, liefert die Funktion einen Wert in
  461. * dem in CDDoSCSIA beschriebenem Format zurück. Wurde seit dem letztem
  462. * Update eine CD eingelegt, wird der TOC neu eingelesen. Entspricht der
  463. * aktuelle Audiostatus AUDIO_STAT_NO_DISK, AUDIO_STAT_NOT_VALID oder
  464. * AUDIO_STAT_NONE, werden die Positionsfelder der CDx-Struktur auf 0 gesetzt.
  465. *
  466.   CNOP 0,2
  467.   xdef _CDUpdateA
  468. _CDUpdateA:     movem.l d1-d3/a0-a2,-(sp)
  469.  
  470.                 moveq   #10,d0                  ; 10 Byte Kommando
  471.                 moveq   #SCSIF_AUTOSENSE|SCSIF_READ,d1
  472.                 lea     CMDReadSubCh(pc),a1
  473.                 bsr     CDDoSCSIA               ; Kommando ausführen
  474.                 beq     .DiscChanged            ; alles korrekt
  475.  
  476.                 cmp.l   #$023A00,d0             ; NO MEDIA PRESENT ?
  477.                 bne     .EXIT                   ; unerwarteter Fehler
  478.  
  479.                 move.b  #AUDIO_STAT_NO_DISK,cdx_AudioStatus(a0)
  480.                 move.b  #AUDIO_STAT_NO_DISK,cdx_Active(a0)
  481.  
  482. .NoCD           move.l  cdx_TOCData(a0),a1      ; keine CD eingelegt: alles
  483.                 moveq   #3,d1                   ;  CD spezifische löschen
  484. .loop           clr.l   (a1)+                   ; FirstTrack/LastTrack/FirstAudioTrack/reserved3/FirstAudioAddress
  485.                 dbra    d1,.loop                ; und Entry[0] löschen
  486.  
  487. .Stopped        clr.w   (a0)+                   ; cdx_CurrentTrack/CurrentIndex
  488.                 moveq   #4,d1
  489. .loop2          clr.l   (a0)+                   ; cdx_CurrentAbsAddr/CurrentRelAddr/RelRemainBlocks/AbsRemainBlocks/TrackLength
  490.                 dbra    d1,.loop2
  491.                 bra     .EXIT
  492.  
  493. .SetSimpleStat  move.b  #AUDIO_STAT_STOPPED,cdx_Active(a0)
  494.                 bra     .Stopped
  495.  
  496. .DiscChanged    cmp.b   #AUDIO_STAT_NO_DISK,cdx_AudioStatus(a0)    ; neue Disk eingelegt?
  497.                 bne     .UpdateCDx
  498.                 bsr     _CDReadTOCA             ; ja: Table Of Contents neu einlesen
  499.  
  500. .UpdateCDx      move.l  cdx_SCSIData(a0),a1
  501.                 addq.l  #1,a1
  502.                 move.b  (a1)+,d0                ; Audio Status lesen
  503.                 move.b  d0,cdx_AudioStatus(a0)  ;  und setzen
  504.                 move.b  d0,cdx_Active(a0)
  505.                 beq     .SetSimpleStat          ; AUDIO_STAT_NOT_VALID (=0)
  506.                 cmp.b   #AUDIO_STAT_COMPLETED,d0
  507.                 bcc     .SetSimpleStat          ; d0 >= AUDIO_STAT_COMPLETED (STOPPED/NONE)
  508.                                                 ; übrig bleibt PLAY und PAUSE: Positionen lesen
  509.                 moveq   #0,d0                   ; alles okay: RETURN_OK
  510.  
  511. .EXIT           movem.l (sp)+,d1-d3/a0-a2
  512.                 rts
  513.  
  514. CMDReadSubCh:   dc.b    $42, 0, $40, 1, 0, 0, 0, 0, 16, 0
  515.  
  516.  
  517. ************************ CDReadTOCA() ********************************
  518. *
  519. *  LONG CDReadTOCA(register __a0 struct CDxRequest *cdx);
  520. *
  521.   CNOP 0,2
  522.   xdef _CDReadTOCA
  523. _CDReadTOCA:    movem.l d1-d3/a0-a3/a6,-(sp)
  524.  
  525.                 moveq   #10,d0
  526.                 moveq   #SCSIF_AUTOSENSE|SCSIF_READ,d1
  527.                 lea     CMDReadTOC(pc),a1
  528.                 bsr     CDDoSCSIA
  529.                 bne     .EXIT
  530.  
  531.                 move.l  cdx_SCSIData(a0),a1
  532.                 move.w  (a1)+,d0                ; TOC Data Length
  533.                 beq     .EXIT
  534.  
  535.                 move.l  cdx_TOCData(a0),a0      ; da soll alles hin
  536.                 move.w  (a1),(a0)+              ; First und Last Track
  537.  
  538.                 move.b  (a1)+,d1                ; FirstTrack
  539.                 moveq   #0,d3
  540.                 move.b  (a1)+,d3                ; LastTrack
  541.                 sub.b   d1,d3
  542.                 addq.b  #1,d3                   ; d3=Track Anzahl
  543.  
  544.                 move.l  a0,a3                   ; für später
  545.                 clr.w   (a0)+                   ; wird nachher gefüllt...
  546.                 clr.l   (a0)+                   ; (TrackNum/FirstAudioTrack/FirstAudioAddress)
  547.  
  548.                 move.l  a0,a2                   ; Track 0 gibt's nicht, da kommt
  549.                 clr.l   (a0)+                   ;  nacher die logical block
  550.                 clr.l   (a0)+                   ;  address der lead-out area rein
  551.  
  552.                 clr.l   16(a0)                  ; Entry für Track 3 sicherheitshalber löschen
  553.                 clr.l   20(a0)                  ; (für ID Berechnung :-)
  554.  
  555.                 lsr.l   #3,d0                   ; durch 8 (pro Entry 8 bytes)
  556.                                                 ; die 2 bytes für F. und L. Track fallen raus
  557.                 subq.l  #1,d0                   ; dbra endet bei -1
  558.                 bmi     .Good                   ; jetzt schon -1?
  559.  
  560.                 moveq   #-1,d2                  ; noch keinen AudioTrack gefunden...
  561.  
  562. .loop           move.l  (a1)+,d1
  563.                 move.l  d1,(a0)+                ; ersten 4 bytes (8 bytes / Entry) kopieren
  564.                 tst.b   d2                      ; schon AudioTrack gefunden?
  565.                 beq     .loopend
  566.                 btst.l  #18,d1                  ; AudioTrack?
  567.                 bne     .loopend
  568.                 move.b  d3,(a3)+                ; TrackNum
  569.                 lsr.w   #8,d1
  570.                 move.b  d1,(a3)+                ; FirstAudioTrack
  571.                 move.l  (a1),-4(a2)             ; FirstAudioAddress
  572.                 moveq   #0,d2
  573. .loopend        move.l  (a1)+,(a0)+             ; letzten 4 Bytes kopieren
  574.                 dbra    d0,.loop
  575.  
  576. .LeadOut        subq.l  #8,a1                   ; letzten Entry nochmal holen
  577.                 cmp.b   #$AA,2(a1)              ; wirklich lead out area? (Tracknr. $AA)
  578.                 bne     .Good
  579.                 move.l  (a1)+,(a2)+             ; ja: nochmal nach Entry[0] kopieren
  580.                 move.l  (a1),(a2)
  581.  
  582. .CalcID         move.l  4.w,a6
  583.                 lea     IDFormat(pc),a0
  584.                 move.l  (a2),-(a7)              ; Entry[0].Address
  585.                 move.l  24(a2),-(a7)            ; Entry[3].Address
  586.                 move.l  d3,-(a7)                ; LastTrack-FirstTrack+1
  587.                 move.l  a7,a1
  588.                 lea     CDID-(Entry+4)(a2),a3
  589.                 lea     PutChProc(pc),a2
  590.                 jsr     _LVORawDoFmt(a6)        ; ID formatieren
  591.                 lea     12(a7),a7
  592.  
  593. .Good           moveq   #0,d0
  594.  
  595. .EXIT           movem.l (sp)+,d1-d3/a0-a3/a6
  596.                 rts
  597.  
  598. CMDReadTOC: dc.b $43, 0, 0, 0, 0, 0, 0, $3, $24, 0
  599. IDFormat:   dc.b '%02ld%06lx%06lx',0
  600.  
  601.  
  602. ************************ CDTestUnitA() ******************************
  603. *
  604. *  LONG CDTestUnitA(register __a0 struct CDxRequest *cdx);
  605. *
  606. * Testet die logical unit ob sie bereit ist. Wenn sie das ist, wird GOOD (0)
  607. * zurückgegeben, ansonsten ein Returncode im in CDDoSCSIA beschriebenem
  608. * Format.
  609. *
  610.   CNOP 0,2
  611.   xdef _CDTestUnitA
  612. _CDTestUnitA:   movem.l d1/a0-a1,-(sp)
  613.  
  614.                 moveq   #6,d0                           ; 6 Byte Kommando
  615.                 moveq   #SCSIF_AUTOSENSE,d1             ; REQUEST SENSE ausführen lassen
  616.                 lea     CMDReadSubCh(pc),a1
  617.                 bsr     CDDoSCSIA                       ; Kommando ausführen
  618.  
  619. .EXIT           movem.l (sp)+,d1/a0-a1
  620.                 rts
  621.  
  622. CMDTestUnitReady:   dc.b    $0, 0, 0, 0, 0, 0
  623.  
  624.  
  625. ************************ CDEjectA() *********************************
  626. *
  627. *  LONG CDEjectA(register __a0 struct CDxRequest *cdx, register __d0 BOOL really);
  628. *
  629. * TRUE öffnet die Schublade, FALSE schließt sie. Im Fehlerfall (Schublade
  630. * schon offen/geschlossen) wird ein Fehlercode zurückgegeben. Außerdem
  631. * wird das Flag JUSTCLOSED gesetzt, wenn die Schublade geschlossen werden
  632. * soll, sonst wird es gelöscht.
  633. *
  634.   CNOP 0,2
  635.   xdef _CDEjectA
  636. _CDEjectA:      movem.l d1/a0-a1,-(sp)
  637.  
  638.                 lea     CMDStartStopUnit(pc),a1
  639.  
  640. .eject          moveq   #2,d1
  641.                 and.b   #~SPECIALF_JUSTCLOSED,cdx_Flags(a0)
  642.                 tst.l   d0
  643.                 bne     .goon
  644. .load           moveq   #3,d1
  645.                 or.b    #SPECIALF_JUSTCLOSED,cdx_Flags(a0)
  646. .goon           move.b  d1,4(a1)
  647.                 moveq   #6,d0
  648.                 moveq   #SCSIF_AUTOSENSE|SCSIF_READ,d1
  649.                 bsr     CDDoSCSIA
  650.  
  651. .EXIT           movem.l (sp)+,d1/a0-a1
  652.                 rts
  653.  
  654. CMDStartStopUnit:   dc.b $1B, 1, 0, 0, 2, 0
  655.  
  656. UnknownVendor:  dcb.b   9
  657.