home *** CD-ROM | disk | FTP | other *** search
- include "exec/types.i"
- include "exec/nodes.i"
- include "exec/lists.i"
- include "exec/memory.i"
- include "exec/ports.i"
- include "exec/io.i"
- include "exec/devices.i"
- include "exec/resident.i"
- include "devices/trackdisk.i"
- include "dos.i"
-
- xref _LVOOpenLibrary,_LVOCloseLibrary
- xref _LVOAllocSignal,_LVOFreeSignal,_LVOFindTask
- xref _LVOAddPort,_LVORemPort
- xref _LVOOpenDevice,_LVOCloseDevice,_LVODoIO
- xref _LVORawDoFmt,_LVOAllocMem,_LVOFreeMem
- xref _LVOFindResident,_LVOOutput,_LVOWrite
- xref _LVOLoadSeg,_LVOUnLoadSeg
-
- BOOTSIZE equ 1024 ; boottilohkon koko tavuina
- BUF equ 2048 ; koodipuskurin koko
- LF equ 10 ; rivinsiirto
-
- .DosBase equ -4 ; dos-kirjaston perusosoite pinossa
- port equ -8 ; viestiportin osoite pinossa
- ioreq equ -12 ; ioreq-osoitin
- buf equ -16 ; puskurin osoite
- seglist equ -20 ; segmenttilistan osoitin
- unit equ -24 ; levyaseman numero
- filename equ -28 ; tiedoston nimen osoitin
- devflag equ -30 ; lippu: trackdisk auki
-
- Start link a4,#-30
- clr.b -1(a0,d0.l) ; lisätään loppunolla
- move.l a0,a5 ; komentorivin osoite
-
- moveq #6,d0
- move.l a4,a0
- 1$ clr.l -(a0) ; nollataan muuttujat
- dbf d0,1$
- clr.w -(a0)
-
- lea dosname,a1 ; dos-kirjaston nimi
- moveq #0,d0 ; mikä tahansa versio
- move.l $4,a6 ; avataan dos
- jsr _LVOOpenLibrary(a6)
- move.l d0,.DosBase(a4) ; perusosoite talteen
- beq cleanup ; jos ei auennut, pois
-
- move.l #BUF,d0 ; puskurin koko
- move.l #MEMF_CHIP!MEMF_CLEAR,d1; tyyppi=CHIP-muisti
- move.l $4,a6
- jsr _LVOAllocMem(a6) ; varataan puskuri
- move.l d0,buf(a4) ; osoite talteen
- beq cleanup ; jos ei puskuria, pois
- move.l d0,a0
- lea.l BOOTSIZE(a0),a0
- move.l a0,filename(a4) ; filename = buf + BOOTSIZE
-
- move.l a5,a0 ; komentorivin osoite
- bsr parse ; nuuskitaan komentorivi
- move.l a0,d0
- bne cmderr ; virhe: pois
-
- moveq.l #MP_SIZE,d0 ; viestiportin koko
- sub.l a0,a0 ; ei nimeä (yksit. portti)
- bsr createport ; luodaan portti
- move.l d0,port(a4) ; osoite talteen
- beq cleanup ; jos ei porttia, pois
-
- moveq.l #IOSTD_SIZE,d0 ; IORequestin koko
- move.l port(a4),a0 ; viestiportin osoite
- bsr createio ; luodaan IOReq
- move.l d0,ioreq(a4) ; osoite talteen
- beq cleanup ; jos ei IOReq:a, pois
-
- lea INITIAL(pc),a0 ; kopioidaan puskuriin..
- moveq #(USERCODE-INITIAL),d0 ; ..näin monta tavua
- move.l d0,d1
- subq.l #1,d0 ; dbf:lle yhtä pienempi luku
- move.l buf(a4),a2 ; puskurin osoite
- cploop move.b (a0)+,(a2)+ ; kopioidaan koodia..
- dbf d0,cploop ; ..kunnes loppu
-
- move.l #BOOTSIZE,d2 ; boottilohko BOOTSIZE tavua
- sub.l d1,d2 ; d2 = jäljelle jäävän koko
- move.l filename(a4),d1 ; ladattava tiedosto
- move.l .DosBase(a4),a6
- jsr _LVOLoadSeg(a6) ; ladataan se muistiin
- move.l d0,seglist(a4) ; seglistin osoitin talteen
- bne.s ck_len ; hyppy jos latautui
- lea eltxt(pc),a0 ; virheilmoitus, jos..
- move.l filename(a4),d0 ; ..ei saatu ladattua
- bsr dpymsg ; tulostetaan virhe
- bra cleanup ; pois
-
- ck_len add.l d0,d0 ; muunnetaan BCPL-osoitin..
- add.l d0,d0 ; ..abs. osoitteeksi
- move.l d0,a0 ; osoite a0:aan
-
- tst.l (a0) ; onko useita segmenttejä?
- bne multip ; on, hyppää ja valita
- move.l -(a0),d0 ; segmentin koko d0:aan
- cmp.l d2,d0 ; riittääkö tila?
- bhi toolong ; ei, hyppää ja valita
- addq.l #8,a0 ; segm. koodi alkaa tästä
- subq.l #1,d0 ; kopioitava määrä
- cp_code move.b (a0)+,(a2)+ ; kopioidaan puskuriin..
- dbf d0,cp_code ; ..kunnes segmentti kopiotu
-
- ; Lasketaan boottilohkon tarkistussumma. Kun kaikki 256 long wordia
- ; lasketaan yhteen, tuloksen on oltava nolla. Jokaisen yhteenlaskun
- ; jälkeen tarkistetaan carry-bitin tila ja lisätään summaan ykkönen,
- ; jos carry oli 1 (yhteenlaskussa syntyi ylivuoto). Lopuksi asete-
- ; taan tarkistussumma sellaiseksi, että summasta tosiaan tulee nolla.
- move.l buf(a4),a0 ; puskurin osoite
- move.l a0,a1 ; myös a1:een
- move.w #BOOTSIZE/4-1,d1 ; lohkon koko longeina
- moveq #0,d0 ; summa alussa = 0
- c_csum add.l (a0)+,d0 ; lisätään jokainen LONG
- bcc.s 1$ ; jos muistinumero, ..
- addq.l #1,d0 ; ..lisätään vielä ykkönen
- 1$ dbf d1,c_csum ; lasketaan kaikki
- move.l buf(a4),a0 ; puskurin osoite
- addq.l #4,a0 ; offset tarkistussummaan
- sub.l d0,(a0) ; vähenn. tarkistussummasta
- bcc.s 2$ ; pitikö lainata?
- subq.l #1,(a0) ; joo, vähennetään vielä 1
-
- 2$ lea TDname(pc),a0 ; laitenimi
- move.l unit(a4),d0 ; yksikkö
- move.l ioreq(a4),a1 ; IORequestin osoite
- moveq.l #0,d1 ; liput
- move.l $4,a6
- jsr _LVOOpenDevice(a6) ; avataan trackdisk
- tst.l d0 ; saatiinko auki?
- beq.s dev_ok ; joo, hyppää
-
- lea optxt(pc),a0
- move.l unit(a4),d0 ; yksikkö
- bsr dpymsg ; tulostetaan virhe
- bra cleanup ; pois
-
- dev_ok st devflag(a4) ; trackdisk saatiin auki
- moveq #1,d0 ; käynnistetään moottori
- bsr Motor
- bsr WriteBlk ; kirjoitetaan boottilohko
- bne.s wrerr ; kirjoitus ei onnistunut
-
- moveq #0,d0
- bsr Motor ; pysäytetään moottori
- bra cleanup ; siivotaan jäljet
-
-
- wrerr lea wrtxt(pc),a0 ; virheilmoituksia
- bra.s cmderr
-
- multip lea ootxt(pc),a0
- bra.s cmderr
-
- toolong lea tltxt(pc),a0
- move.l d2,d1
- cmderr bsr dpymsg
- cleanup tst.b devflag(a4) ; onko trackdisk auki?
- beq.s 100$
- move.l ioreq(a4),a1
- move.l $4,a6
- jsr _LVOCloseDevice(a6) ; on -> suljetaan se
-
- 100$ move.l ioreq(a4),a0 ; vapautetaan IOReq
- bsr deleteio
- move.l port(a4),a0 ; vapautetaan MsgPort
- bsr deleteport
-
- move.l seglist(a4),d1 ; segmenttilista olemassa?
- beq.s 103$
- move.l .DosBase(a4),a6
- jsr _LVOUnLoadSeg(a6) ; joo -> vapautetaan se
-
- 103$ move.l buf(a4),d0 ; puskuri varattu?
- beq.s 105$
- move.l d0,a1
- move.l #BUF,d0
- move.l $4,a6
- jsr _LVOFreeMem(a6) ; jep -> vapautetaan se
-
- 105$ move.l .DosBase(a4),d0 ; suljetaan Dos-kirjasto
- beq.s 107$
- move.l d0,a1
- move.l $4,a6
- jsr _LVOCloseLibrary(a6)
- 107$ unlk a4
- rts
-
- skipblk move.b (a0)+,d0 ; hypätään välilyöntien ja
- beq.s 10$ ; tabulaattorien yli
- cmp.b #32,d0
- beq.s skipblk
- cmp.b #9,d0
- beq.s skipblk
- 10$ subq.l #1,a0
- rts
-
- ;;;; tutkitaan komentorivin parametrit
- parse bsr.s skipblk ; hypätään rivin alussa tyhjän yli
- beq perr1 ; jos rivi loppui, virhe
- moveq #34,d1 ; lainausmerkki d1:een
- move.l filename(a4),a1 ; tila tiedoston nimelle
- move.b (a0)+,d0 ; otetaan merkki komentoriviltä
- beq perr1 ; jos nolla, virhe
- cmp.b d1,d0 ; lainausmerkki?
- bne.s 101$ ; ei -> hypellään yli
- 10$ move.b (a0)+,d0 ; kopioidaan tiedoston nimeä,
- beq.s 11$ ; kunnes .. .. nolla ..
- cmp.b d1,d0 ; .. tai lainausmerkki
- beq.s 11$
- move.b d0,(a1)+ ; merkki talteen nimipuskuriin
- bra.s 10$ ; kopioidaan koko nimi
-
- 100$ move.b (a0)+,d0 ; kopioidaan nimeä, kunnes...
- beq.s 11$ ; .. nolla ...
- 101$ cmp.b #' ',d0 ; .. tai välilyönti ..
- beq.s 11$
- cmp.b #9,d0 ; .. tai tabulaattori
- beq.s 11$
- move.b d0,(a1)+ ; merkki talteen
- bra.s 100$
- 11$ clr.b (a1) ; lisätään nimen loppuun nolla
- bsr.s skipblk ; hypätään mahdollisen tyhjän yli
-
- move.b (a0)+,d0 ; otetaan levyaseman numero
- beq.s perr2
- bsr.s ucase
- cmp.b #'D',d0 ; 'D'
- bne.s perr2
- move.b (a0)+,d0
- beq.s perr2
- bsr.s ucase
- cmp.b #'F',d0 ; 'F'
- bne.s perr2
- moveq #0,d0
- move.b (a0)+,d0
- beq.s perr2
- sub.b #'0',d0 ; '0'...'3'
- cmp.b #3,d0
- bhi.s perr2
- move.l d0,unit(a4)
- cmp.b #':',(a0) ; kaksoispiste?
- bne.s perr2
- sub.l a0,a0 ; ei virhettä
- rts
- perr1 lea fntxt(pc),a0
- rts
- perr2 lea ddtxt(pc),a0
- rts
-
- ucase cmp.b #'a',d0 ; muunnetaan ISOKSI KIRJAIMEKSI
- bcs.s 10$ ; alle 'a'?
- cmp.b #'z',d0
- bhi.s 10$ ; yli 'z'?
- sub.b #('a'-'A'),d0 ; ISONNA
- 10$ rts
-
- ; dpymsg tulostaa a0:n osoittaman merkkijonon ja sen mahdollisesti
- ; sisältämät muuttujat d0...d7 C-kielen printf-lauseen tavoin.
- dpymsg movem.l d0-d7/a0-a3,-(sp) ; rekisterit pinoon
- move.l sp,a1
- lea.l 110$(pc),a2 ; putchar-rutiinin osoite
- move.l buf(a4),a3 ; tulostuspuskuri
- move.l $4,a6
- jsr _LVORawDoFmt(a6) ; muotoillaan rivi
- move.l .DosBase(a4),a6
- jsr _LVOOutput(a6) ; tulostustiedosto
- move.l d0,d1
- beq.s 105$
- move.l a3,d2
- 100$ tst.b (a3)+ ; lasketaan rivin pituus
- bne.s 100$
- subq.w #1,a3
- move.l a3,d3
- sub.l d2,d3
- jsr _LVOWrite(a6) ; tulostetaan rivi
- movem.l (sp)+,d0-d7/a0-a3 ; rekisterit takaisin
- 105$ rts
- 110$ move.b d0,(a3)+ ; putchar-rutiini
- rts
-
- ; port = createport(size,name);
- ; d0 d0 a0
- ;
- createport:
- movem.l d2-d3/a2-a3,-(sp)
- move.l d0,d3 ; koko
- move.l a0,a3 ; nimen osoite
- move.l a0,d1 ; nimen osoite = 0?
- beq.s 10$ ; joo -> ei nimeä
- 1$ tst.b (a0)+ ; mitataan nimen pituus
- bne.s 1$
- sub.l d1,a0
- add.l a0,d0 ; lisätään nimen pituus kokoon
- 10$ addq.l #4,d0 ; tilaa portin koolle (4 tavua)
- move.l d0,d2 ; lopullinen koko talteen
- move.l #1!(1<<16),d1 ; MEMF_PUBLIC!MEMF_CLEAR
- move.l $4,a6 ; ExecBase
- jsr _LVOAllocMem(a6) ; varataan muistia
- move.l d0,a2 ; varatun muistin osoite
- tst.l d0 ; saatiinko muistia?
- beq creaport1 ; ei -> pois
- move.l d2,(a2)+ ; varatun alueen koko muistiin
- moveq.l #-1,d0 ; varataan signaalibitti
- jsr _LVOAllocSignal(a6)
- move.b d0,MP_SIGBIT(a2) ; asetetaan signaali porttiin
- bmi.s creaporte ; ei saatu signaalia -> pois
- sub.l a1,a1 ; etsitään tämä taski
- jsr _LVOFindTask(a6)
- move.l d0,MP_SIGTASK(a2) ; asetetaan osoite porttiin
- move.b #NT_MSGPORT,LN_TYPE(a2) ; noden tyyppi = MSGPORT
- clr.b MP_FLAGS(a2) ; nollataan liput
-
- move.l a3,d0 ; nimen osoite
- beq.s 20$ ; jos ei nimeä, hypätään
- lea.l 0(a2,d3.l),a0 ; a0 = portin loppuosoite
- move.l a0,LN_NAME(a2) ; asetetaan nimen osoite porttiin
- 2$ move.b (a3)+,(a0)+ ; kopioidaan nimi
- bne.s 2$ ; kunnes NULL
- move.l a2,a1 ; portilla nimi -> lisätään listaan
- jsr _LVOAddPort(a6) ; julkiseksi portiksi
- move.l a2,d0 ; palautetaan portin osoite d0:ssa
- bra.s creaport1
- 20$ lea MP_MSGLIST(a2),a0 ; ei nimeä -> tehdään vain NEWLIST
- NEWLIST A0
- move.l a2,d0 ; palautetaan portin osoite d0:ssa
- bra.s creaport1
-
- ; deleteport(MsgPort);
- ; a0
- ;
- deleteport:
- movem.l d2-d3/a2-a3,-(sp)
- move.l a0,d0 ; portin osoite
- beq.s creaport1 ; jos nolla, ei tehdä mitään
- move.l a0,a2
- tst.l LN_NAME(a2) ; onko portilla nimi?
- beq.s 30$ ; ei -> hyppää
- move.l a2,a1 ; on -> poistetaan portti listalta
- move.l $4,a6 ; ExecBase
- jsr _LVORemPort(a6) ; poistetaan listalta
- 30$ moveq.l #0,d0
- move.b MP_SIGBIT(a2),d0 ; signaalin numero
- bmi.s creaporte ; negatiivinen -> ei signaalia, pois
- move.l $4,a6
- jsr _LVOFreeSignal(a6) ; vapautetaan signaali
- creaporte:
- move.l -(a2),d0 ; d0 = portille varatun alueen koko
- move.l a2,a1 ; a1 = alueen osoite
- move.l $4,a6
- jsr _LVOFreeMem(a6) ; vapautetaan muisti
- moveq.l #0,d0 ; palautetaan nolla
- creaport1:
- movem.l (sp)+,d2-d3/a2-a3
- move.l d0,a0 ; nolla myös a0:aan
- rts
-
- ; IOReq = createio(size,MsgPort);
- ; d0 d0 a0
- ;
- createio:
- movem.l d2/a2,-(sp) ; d0=koko, a0=MsgPort
- move.l a0,a2 ; msgport* talteen
- addq.l #4,d0 ; tilaa stuktuurin koolle
- move.l d0,d2
- move.l #MEMF_PUBLIC!MEMF_CLEAR,d1
- move.l $4,a6
- jsr _LVOAllocMem(a6) ; varataan muistia IORequestille
- move.l d0,a0
- tst.l d0
- beq.s 100$ ; ei muistia -> pois
- move.l d2,(a0)+ ; tallennetaan struktuurin koko
- move.l a2,MN_REPLYPORT(a0) ; portin osoite IORequestiin
- move.b #NT_MESSAGE,LN_TYPE(a0) ; portin tyyppi
- subq.l #4,d2
- move.w d2,MN_LENGTH(a0) ; asetetaan viestin koko
- move.l a0,d0 ; palautetaan struktuurin osoite
- 100$ movem.l (sp)+,d2/a2
- rts
-
- ; deleteio(IOReq);
- ; a0
- ;
- deleteio:
- move.l a0,d0 ; a0 = IoRequest
- beq.s 100$ ; nolla -> ei tehdä mitään
- move.l a0,a1
- move.l -(a1),d0 ; otetaan struktuurin koko
- move.l $4,a6
- jsr _LVOFreeMem(a6) ; vapautetaan muisti
- 100$ rts
-
- ; Motor kytkee levyaseman moottorin päälle tai pois riippuen d0:n
- ; arvosta.
- Motor move.l ioreq(a4),a1 ; IORequest, kuinkas muuten
- move.l d0,IO_LENGTH(a1) ; moottorin tila on/off
- move.w #TD_MOTOR,IO_COMMAND(a1); komento TD_MOTOR
- move.l $4,a6
- jsr _LVODoIO(a6) ; komenna
- rts
-
- ; WriteBlk kirjoittaa boottilohkon levylle trackdisk devicen avulla.
- WriteBlk:
- move.l ioreq(a4),a1 ; IORequest
- clr.l IO_OFFSET(a1) ; aloitetaan lohkosta nolla
- move.l #BOOTSIZE,IO_LENGTH(a1) ; pituus = 1024 tavua
- move.l buf(a4),IO_DATA(a1) ; puskurin osoite
- move.w #CMD_WRITE,IO_COMMAND(a1); IO-komento = WRITE
- move.l a1,a2 ; IOReq talteen
- move.l $4,a6 ; kirjoitetaan boottilohko
- jsr _LVODoIO(a6)
- tst.l d0 ; virhe?
- bne.s WrBlke
-
- move.l a2,a1 ; IOReq taas
- move.w #CMD_UPDATE,IO_COMMAND(a1); update-komento
- jsr _LVODoIO(a6) ; kirjoitetaan puskurit levylle
- tst.l d0 ; virhe?
- WrBlke rts
-
- ; Boottilohkon alkuun kopioitava koodi, joka hoitaa varsinaisen käyttäjän
- ; aliohjelman kutsumisen sekä koneen boottauksen jatkamisen käyttäjän oh-
- ; jelman ajon päätyttyä.
- INITIAL dc.b 'DOS',0 ; levykkeen tyyppi (OFS)
- dc.l 0 ; tarkistussumma (lasketaan myöh.)
- dc.l 880 ; levykkeen root blockin numero
- movem.l d0-d7/a0-a6,-(sp) ; rekisterit pinoon
- clr.l IO_LENGTH(a1) ; moottori sammuksiin
- move.w #TD_MOTOR,IO_COMMAND(a1); moottorin ohjauskomento
- move.l $4,a6 ; sammutetaan moottori
- jsr _LVODoIO(a6)
- movem.l (sp),d0-d7/a0-a6 ; luetaan rekisterien arvot
- bsr.s USERCODE ; kutsutaan käyttäjän koodia
- movem.l (sp)+,d0-d7/a0-a6 ; otetaan rekisterit pinosta
- lea dosname(pc),a1 ; Dos-kirjaston nimi
- jsr _LVOFindResident(a6) ; etsitään dos-resident modulia
- tst.l d0
- beq.s INITIAL_err ; ei löytynyt -> guru
- move.l d0,a0 ; resident-palikka
- move.l RT_INIT(a0),a0 ; resident-palikan alustusrutiini
- moveq #0,d0 ; ei virhettä, jatketaan boottia
- rts
- INITIAL_err:
- moveq #-1,d0 ; virhe, guruillaan
- rts
- dosname dc.b 'dos.library',0 ; nimen pituus parillinen
-
- USERCODE ; käyttäjän koodi tulee tähän
-
- TDname dc.b 'trackdisk.device',0 ; trackdiskin nimi
- eltxt dc.b 'Error loading "%s"',LF,0
- optxt dc.b 'Unable to open unit df%ld:',LF,0
- wrtxt dc.b 'Could not write boot block - error %ld.',LF,0
- ootxt dc.b 'Only one segment allowed.',LF,0
- tltxt dc.b 'Length %ld (space %ld).',LF,0
- fntxt dc.b 'error in filename',LF,0
- ddtxt dc.b 'give destination drive dfN: where N is 0...3',LF,0
- ds.w 0
-
- end
-
-