;=============================================================================
;                             PCMCIA Card Info
;=============================================================================
;
;
;  History:
;
; 30-06-97 - Now releases card if attribute presence test fails.
;
; 31-08-97 - Reads config and configmap tuples to get config ID
;
; 11-12-97 - More analysis of tuples.
;

VERSION  = 0
REVISION = 2


; opt d+

 output ram:card_info

 include start.i
 include pcmcia.i
 include cnet.i

 include printf.i

; LONGWINDED=1  to print more sub-tuple details!

atmemsize= 4096
cmemsize = 2048-16-16

_main:
 move.l  ourtask(pc),a0
 tst.l   pr_cli(a0)
 bne.s   .cli
 lea     consolename(pc),a0
 move.l  a0,d1
 move.l  #MODE_NEWFILE,d2
 DOS     Open
 move.l  d0,ohandle
 beq     _exit
 bra.s   .start
.cli:
 dos     output
 move.l  d0,ohandle
.start:
 printf  <10,"Getting PCMCIA card info...",10,10>

 move.l  4.w,a6
 lea     cardname(pc),a1
 jsr     _LVOOpenResource(a6)         ; open credit card resource
 move.l  d0,cardres
 beq.s   error
 move.l  d0,a6
 lea     card_handle(pc),a1
 lea     cardremoved(pc),a0
 move.l  a0,cah_CardRemoved(a1)
 lea     cardinserted(pc),a0
 move.l  a0,cah_CardInserted(a1)      ; set interrupt vectors
 lea     cardstatus(pc),a0
 move.l  a0,cah_CardStatus(a1)
 lea     ourname(pc),a0
 move.l  a0,ln_name(a1)
 move.b  #20,ln_pri(a1)
 move.b  #CARDF_IFAVAILABLE|CARDF_POSTSTATUS,cah_cardflags(a1)
_start:
 jsr     _LVOOwnCard(a6)              ; own card (sets up interrupt vectors)
 tst.l   d0
 beq.s   owned
error:
 printf  <"Card is not inserted, or is already in use!",10>
 moveq   #-1,d0                       ; error if can't own card
 bra     _done
owned:
 lea     card_handle(pc),a1
 move.l  #CARDF_DISABLE_WP|CARDF_ENABLE_DIGAUDIO,d1
 jsr     _LVOCardMiscControl(a6)      ; enable card I/O functions

 lea     $a00000,a0
 cmp.b   #$01,(a0)
 beq.s   .good
 printf  <"Attribute memory not detected!",10,"Re-insert card and try again.",10>
 bra     _releasecard
.good:
 lea     atmem(pc),a1
 move.l  #(atmemsize/2)-1,d0
.getattr
 move.b  (a0)+,(a1)+                  ; get attribute memory
 addq.l  #1,a0                        ; skipping odd bytes
 dbf     d0,.getattr

 lea     card_handle(pc),a1
 lea     tuple(pc),a0
 moveq   #CISTPL_INFO_V1,d1
 move.l  #256,d0
 jsr     _LVOCopyTuple(a6)            ; get info tuple
 tst.l   d0
 beq     .getfid
.got_info
 lea     tuple(pc),a0
 moveq   #0,d2
 move.b  1(a0),d2
 subq.w  #1,d2
 bmi     .getfid
 lea     2(a0),a0
.showinfo:
 moveq   #0,d0
 move.b  (a0)+,d0
 cmp.b   #$ff,d0
 beq.s   .endascii
 cmp.b   #' ',d0
 bhs.s   .ascii
 move.b  #'.',d0
.ascii:
 printf  <"%lc">,d0                   ; show information as ascii string
 dbf     d2,.showinfo
.endascii:
 printf  <10,10>
.getfid:
 lea     card_handle(pc),a1
 lea     tuple(pc),a0
 moveq   #CISTPL_FUNC_ID,d1
 move.l  #256,d0
 jsr     _LVOCopyTuple(a6)            ; get Function ID tuple
 tst.l   d0
 beq     .getconfigmap
.got_func_id:
 lea     tuple(pc),a0
 moveq   #0,d0
 move.b  2(a0),d0
 cmp.b   #9,d0
 blo.s   .goodfunc
 printf  <"Card function is unknown",10,10>
 bra.s   .getconfigmap
.goodfunc:
 lsl.w   #2,d0
 lea     functab(pc),a0
 move.l  (a0,d0.w),a0
 printf  <"Appears to be a %s card",10,10>,a0
.getconfigmap:
 lea     card_handle(pc),a1
 lea     tuple(pc),a0
 moveq   #CISTPL_CONF_MAP,d1
 move.l  #256,d0
 jsr     _LVOCopyTuple(a6)            ; get config map tuple
 tst.l   d0
 bne.s   .got_configmap
 printf  <"No Config Map tuple found",10>
 bra     .save
.got_configmap:
 lea     tuple(pc),a0
 move.b  2(a0),d2
 move.b  d2,d0
 and.w   #$03,d0                      ; (number of address bytes)-1
 moveq   #0,d6
.getconfigaddr:
 lsl.l   #8,d6
 move.b  4(a0,d0.w),d6                ; collect config register address
 dbf     d0,.getconfigaddr

 lea     card_handle(pc),a1
 lea     tuple(pc),a0
 moveq   #CISTPL_CONFIG,d1
 move.l  #256,d0
 jsr     _LVOCopyTuple(a6)            ; get config tuple
 tst.l   d0
 bne.s   .gotconfig
 printf  <"No Config tuple found",10>
 bra     .save
.gotconfig:
 moveq   #0,d0
 lea     tuple(pc),a0
 move.b  2(a0),d3
 moveq   #0,d7
 move.b  d3,d7
 and.b   #$3f,d7                      ; extract configuration ID value
 move.b  d2,d0
 and.w   #$03,d0                      ; (number of address bytes)-1
 addq.w  #1,d0
 mulu    #8,d0

 printf  <"CCR Offset address (%ld bit) = $%06lx, Config ID = $%02lx",10,10>,d0,d6,d7

 lea     3(a0),a0
 btst    #7,d3
 beq     .noface
 move.b  (a0)+,d2
 move.b  d2,d0
 and.b   #$0f,d0
 printf  <"Interface Type %ld, uses: ">,d0
 btst    #4,d2
 beq.s   .nobv
 printf  <"BVD ">
.nobv:
 btst    #5,d2
 beq.s   .nowp
 printf  <"WP ">
.nowp:
 btst    #6,d2
 beq.s   .nordy
 printf  <"RDYBSY">
.nordy:
 btst    #7,d2
 beq.s   .nowait
 printf  <"WAIT ">
.nowait:
 printf  <10,10>
.noface:
 IFD     LONGWINDED
 move.b  (a0)+,d2
 move.b  d2,d4
 and.l   #$03,d4
 beq     .nopower
 printf  <"Power sub-tuple(s):",10>
.power:
 bsr     showpower
 subq.b  #1,d4
 bne.s   .power
.nopower:
 btst    #2,d2
 beq     .notime
 printf  <10,"Timing sub-tuple:",10>
 move.b  (a0)+,d1
 move.b  d1,d0
 and.b   #$03,d0
 printf  <" Wait=%ld">,d0
 cmp.b   #3,d0
 beq.s   .noextwait
 move.b  (a0)+,d0
 printf  <" ExtWait=%ld">,d0
.noextwait:
 move.b  d1,d0
 and.b   #$1c,d0
 lsr.b   #2,d0
 printf  <" Ready=%ld">,d0
 cmp.b   #7,d0
 beq.s   .noextready
 move.b  (a0)+,d0
 printf  <" ExtReady=%ld">,d0
.noextready:
 move.b  d1,d0
 and.b   #$e0,d0
 lsr.b   #6,d0
 printf  <" Rsrvd=%ld">,d0
 cmp.b   #7,d0
 beq.s   .noextres
 move.b  (a0)+,d0
 printf  <" ExtRsrvd=%ld">,d0
.noextres:
 printf  <10,10>
.notime:
 btst    #3,d2
 bne     .noio
 printf  <"I/O space sub-tuple:",10>
 move.b  (a0)+,d1
 move.b  d1,d0
 and.b   #$1f,d0
 printf  <" I/O Address lines = $%02lx",10>,d0
 btst    #5,d1
 beq.s   .no8bit
 printf  <" 8bit I/O present",10>
.no8bit:
 btst    #6,d1
 beq.s   .no16bit
 printf  <" 16bit I/O present",10>
.no16bit:
 btst    #7,d1
 beq.s   .norange
 printf  <" I/O has range",10>
.norange:
 movem.l d2-d7,-(sp)
 move.b  (a0)+,d7          ; d7 = count/iosize/blocksize
 move.b  d7,d0
 and.b   #$0f,d0
 printf  <" %ld I/O sub-tuples:",10>
 move.b  d0,d2             ; d2 = number of sub-tuples-1
 move.b  d7,d3
 and.w   #$30,d3
 lsr.b   #4,d3             ; d3 = size of address value
 move.b  d7,d4
 and.w   #$c0,d4
 lsr.b   #6,d4             ; d4 = size of i/o block value
.showio:
 moveq   #0,d0
 move.b  d3,d1
.getaddr
 subq.b  #1,d1
 beq.s   .gotaddr
 lsl.l   #8,d0
 move.b  (a0)+,d0
 bra.s   .getaddr
.gotaddr:
 printf  <" Address = $%08lx, ">,d0
 move.b  d4,d1
 moveq   #0,d0
.getrange:
 subq.b  #1,d1
 beq.s   .gotrange
 lsl.l   #8,d0
 move.b  (a0)+,d0
 bra.s   .getrange
.gotrange:
 printf  <"range = %ld bytes",10>,d0
 dbf     d2,.showio
 movem.l (sp)+,d2-d7
.noio:
 btst    #4,d2
 bne.s   .noirq
 printf  <"IRQ sub-tuple:",10>
 move.b  (a0)+,d1
 btst    #5,d1
 beq.s   .nolev
 printf  <" Level triggered",10>
.nolev:
 btst    #6,d1
 beq.s   .notrig
 printf  <" Pulse triggered",10>
.notrig:
 btst    #4,d1
 beq.s   .nomask
 addq.l  #2,a0        ; skip mask
.nomask:
.noirq:
 move.b  d2,d4
 and.l   #$60,d4
 beq.s   .nomemspace
 lsr.b   #6,d4
 printf  <"%ld memory space sub-tuple(s):",10>,d4
.nomemspace:
 btst    #7,d2
 beq.s   .nomisc
 printf  <"Miscellaneous sub-tuple:",10>
.nomisc:

 ENDC   ; LONGWINDED

 lea     $a00000,a0                   ; a0 = attribute memory
 and.l   #$0001FFFF,d6
 move.b  d7,(a0,d6.l)                 ; configure IO space

 lea     $a00000,a0
 add.l   d6,a0              ; we want to see if ccr value was accepted
 lea     cmem(pc),a1
 move.l  #(cmemsize/2)-1,d0
.getccr
 move.w  (a0)+,(a1)+        ; get card configuration register values
 dbf     d0,.getccr

.save:
 printf  <"Getting I/O memory now - remove card if system freezes!",10>

 lea     $a20000,a0
 lea     imem,a1
 move.l  #(1024)-1,d0
.getio
 move.b  (a0)+,(a1)+                  ; get I/O
 subq.l  #1,d0
 bpl.s   .getio

 printf  <10,"Saving data to %s",10>,#filename

 move.l  #filename,d1
 move.l  #MODE_NEWFILE,d2
 dos     open
 move.l  d0,d4
 bmi.s   _releasecard
 lea     atmem(pc),a0
 move.l  a0,d2
 move.l  #(atmemsize/2)+16+cmemsize+16+1024,d3
 move.l  d4,d1
 dos     write
 move.l  d4,d1
 dos     close

_releasecard:
 lea     card_handle(pc),a1
 moveq   #CARDF_REMOVEHANDLE,d0
 move.l  cardres(pc),a6
 jsr     _LVOReleaseCard(a6)
_done:
 printf  <10,"card_info done.",10>
 move.l  ourtask(pc),a0
 tst.l   pr_cli(a0)
 bne.s   .nocon
 move.l  ohandle(pc),d1
 beq.s   .nocon
 DOS     Close
.nocon:
 moveq   #0,d0
 rts


; show a power sub-tuple

showpower:
 move.l  d2,-(sp)
 move.b  (a0)+,d1        ; get block bitmap
 moveq   #7,d2
.block
 lsr.b   #1,d1
 bcc.s   .noblock        ; bit set = power block exists
.byte:
 move.b  (a0)+,d0
 printf  <" $%02lx">,d0  ; show block byte
 btst    #7,d0           ; any more bytes in block ?
 bne.s   .byte
.noblock:
 dbf     d2,.block       ; next block
 printf  <10>
 move.l  (sp)+,d2
 rts



;============================================================
;             PCMCIA status change interrupt handler
;============================================================
;  input:   d0 = status change(s)
;           a1 = user defined
;
;  output:  d0 must be preserved!
;
;
status_int_code:
 rts


card_inserted_code:
 rts

card_removed_code:
 rts

ourname:
 dc.b "pcmcia test interrupt",0
cardname:
 dc.b "card.resource",0
 even

cardremoved:
 dc.l 0,0
 dc.b 0,0
 dc.l 0
 dc.l 0
 dc.l card_removed_code

cardinserted:
 dc.l 0,0
 dc.b 0,0
 dc.l 0
 dc.l 0
 dc.l card_inserted_code

cardstatus:
 dc.l 0,0
 dc.b 0,0
 dc.l 0
 dc.l 0                 ; value to be placed in A1 at interrupt time
 dc.l status_int_code


functab:
 dc.l func0
 dc.l func1
 dc.l func2
 dc.l func3
 dc.l func4
 dc.l func5
 dc.l func6
 dc.l func7
 dc.l func8
 dc.l func9

func0:
 dc.b "Multifunction",0
func1:
 dc.b "Memory",0
func2:
 dc.b "Serial",0
func3:
 dc.b "Parallel",0
func4:
 dc.b "Fixed",0
func5:
 dc.b "Video",0
func6:
 dc.b "Network",0
func7:
 dc.b "AIMS",0
func8:
 dc.b "SCSI",0
func9:
 dc.b "Unknown",0


consolename:
  dc.b  "CON:10/20/600/170/ card_info /WAIT/CLOSE",0


VersionString:
 dc.b    "$VER: card_info "
 dc.b    (VERSION+"0"),".",(REVISION+"0")," "
 dc.b    __DATE
 dc.b    " by Bruce Abbott",10,0
 even

;--------------------------------------------------------
;                     Global data
;--------------------------------------------------------

cardres:
  dc.l 0             ; card.resource base

tuple:
 ds.b    256+8       ; PCMCIA tuple buffer

card_handle:
  ds.b  cah_sizeof   ; handle for our card

filename:
  dc.b  "t:card_info.bin",0
  even

atmem:
  ds.b  (atmemsize/2)
  dc.b  "===== ccr ======"
cmem:
  ds.b  cmemsize
  dc.b  "===== I/O ======"
imem:
  ds.b  1024
