nedoPC.org

Community of electronics hobbyists established in 2002

...
Atom Feed | View unanswered posts | View active topics It is currently 12 Dec 2018 13:52



Reply to topic  [ 47 posts ]  Go to page Previous  1, 2, 3, 4
Изделие МНК-11-01.ДМ 
Author Message
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 17209
Location: Colorado
Reply with quote
А каким софтом такой IDE управляется?

_________________
:eugeek: https://twitter.com/Shaos1973


06 Aug 2018 19:47
Profile WWW
Doomed

Joined: 25 Aug 2009 08:02
Posts: 362
Location: Москва
Reply with quote
Shaos wrote:
А каким софтом такой IDE управляется?

О, это был долгий и увлекательнейший квест. Сначала на тестовых программках потренировался в программировании DMA и регистров ATA, в разных режимах, и как оно должно быть в норме, и симулируя всякие ошибки. В данном деле помогал уже упомянутый инструмент PDP11GUI. ODT, который я написал и зашил в ПЗУшку, обеспечивает стандартный диалог, поэтому в настройках PDP11GUI только указал подходящий вариант PDP-11 и получил удобное средство написания и запуска коротеньких тестовых программок. PDP11GUI имеет встроенный ассемблер, воспринимает синткасис MACRO11, генерирует бинарный файл и через диалог с ODT загружает его в память машины.

Дальше, параллельно, воспользовался технологией загрузки операционки RT-11 через порт системного терминала. Трудностей также не возникло, потому что архитектура моей машинки похожа на ДВК-1. Убедился, таким образом, в работоспособности под операционкой RT-11. Эта же технология позволяет подставлять операционке образы дисков из файлов, эти же образы могут быть подставлены как диски в симуляторе SimH. И эти же образы могут подставляться и в TotalCommander при помощи специального плагина. То есть, имеется средство перемещения файлов между виртуальной машиной в SimH, моей настоящей машиной и вендовым TotalCommander.

Следующий процесс выглядел так. Изучил руководство по написанию драйверов устройств в RT-11 (там они называются device handlers, что по моему мнению более точно отображают их суть по сравнению с названием device drivers). В Notepad++ сочинял и редактировал исходный текст handler'а, в SimH ассемблировал и линковал, на своей машине пробовал, что получилось.

Когда драйвер более-менее получился, настал момент установки RT-11 на жесткий диск, что и было сделано, вместе с написанием начального загрузчика и допрограммированием его в ПЗУ.

В результате на данный момент имеется компактная машинка, почти полноценная PDP-11, самый близкий аналог PDP-11/03. Из периферии - стандартный системный терминал, таймер 50 Гц, ATA диск с обменом по DMA. На диске установлена RT-11.

Текст драйвера получился вот такой, см. ниже. Для вычисления адреса сектора из номера блока придумал алгоритм деления, который получился достаточно быстрым (подпрограмма DIVC). Скорее всего, он уже известен, но я готовые искать не стал, а сел с листом бумаги и придумал. Время деления на константу менее 170 мкс. Потом сравнил с готовым из исходников RT-11, мой раза в полтора лучше.

Code:
.TITLE  AD
;       ATA DISK HANDLER FOR CUSTOM HARDWARE
;       AUTHOR MIXA64

; PREAMBLE

.SBTTL  PREAMBLE SECTION
.MCALL  .DRDEF, .ADDR
.DRDEF  AD, 53, FILST$, 39000., 177400, 220

        DM$VEC  = AD$VEC+4

        ADDMCS  = AD$CSR        ; CSR FOR DMA CONTROLLER
        ADDMWC  = ADDMCS+2      ; WORD COUNT FOR DMA CONTROLLER, NEGATIVE
        ADDMBA  = ADDMCS+4      ; BASE ADDRESS FOR DMA BLOCK
        ADACS0  = ADDMCS+6      ; ATA CS0 ACCESS
        ADACS1  = ADDMCS+10     ; ATA CS1 ACCESS, BYTE
        ADXREG  = ADDMCS+11     ; INDEX REGISTER FOR ATA BUS ADDRESS, BYTE
        ADINCS  = ADDMCS+12     ; CSR FOR INTERRUPT CONTROLLER
        ADDVEC  = ADDMCS+14     ; VECTOR ADDRESS FOR DMA INTERRUPT
        ADAVEC  = ADDMCS+16     ; VECTOR ADDRESS FOR ATA INTERRUPT

        ADECNT  = 4             ; RETRY COUNTS IN CASE OF AN ERROR
        ADNREG  = 4             ; NUMBER OF AD$CSR-BASED REGS TO LOG

        ATA.IM  = 040           ; INTERRUPT MASK
        DMA.IM  = 020           ; INTERRUPT MASK

; HEADER
.SBTTL  HEADER SECTION
.DRBEG  AD

; I/O INITIATION
.SBTTL  I/O INITIATION SECTION

; REGISTER ALLOCATION FOR DIVIDE SUBROUTINE
        QUOT   = %3
        REMNDR = %1        ; DIVIDEND AND REMINDER
        DIVSR  = %2
        DCNTR  = %0

        MOV     #ADECNT, (PC)+
RETRY:  .WORD   0
        CLR     (PC)+
FLAGS:  .WORD   0
        MOV     ADCQE, R5       ; GET CURRENT QUEUE ELEMENT POINTER
                                ; DDCQE POINTS TO Q.BLKN
                                ; QUEUE ELEMENT STRUCTURE FRAGMENT:
                                ; -4: Q.LINK
                                ; -2: Q.CSW
                                ; +0: Q.BLKN PHYSICAL BLOCK NUMBER (PBN)
                                ; +2: Q.FUNC, Q.UNIT, Q.JNUM RESERVED[15], JOBNUMBER[14:11], DEVUNIT[10:8],
                                ; +4: Q.BUFF USER BUFFER ADDRESS
                                ; +6: Q.WCNT WORD COUNT
                                ; WCNT > 0 MEANS READ
                                ; WCNT < 0 MEANS WRITE
                                ; WCNT = 0 MEANS SEEK
                                ; NOTES:
                                ; - UNIT NUMBER IS NOT USED IN EARLY EXPERIMENTAL VERSION, ASSUMED UNIT 0 ON
                                ; - SEEK ACTUALLY MEANS DO NOTHING
                                ;
                                ; ACCEPTED GEOMETRY IS 17 SECTORS 5 HEADS 1027+ CYLINDERS
                                ; CYLINDER IS (PBN/85)
                                ; HEAD N IS (REMAINDER OF (PBN/85))/17, SECTOR N IS REMAINDER OF IT + 1
        .ADDR   #CMDBLK, R4
        MOV     R4, CBADDR      ; SAVE TASK FILE ADDRESS FOR FUTURE USE
        MOV     (R5)+, (PC)+
PBN:    .WORD   0               ; PHYSICAL BLOCK NUMBER, BASE OF TRANSACTION

        MOV     (R5)+, (PC)+
UNIT:   .WORD   0               ; CONTAINS UNIT NUMBER, SPECIAL FUNCTION CODE, JOB NUMBER

        MOV     (R5)+, @#ADDMBA ; USER BUFFER BASE ADDRESS FOR CURRENT TRANSACTION
        MOV     #040, R0        ; ASSUME READ SECTOR COMMAND
        MOV     (R5), R1        ; WCNT COPY HERE
        BNE     20$             ; TO NOP
        JMP     ADEXIT
20$:    BPL     10$             ; TO READ
        NEG     R1
        MOV     #060, R0        ; IT WAS WRITE SECTOR COMMAND
        BIS     #100000, FLAGS  ; SET WRITE BIT IN FLAGS
10$:    MOV     R0, 12(R4)      ; COMMAND CODE IS READY, PUT IT IN IT'S PLACE IN CMDBLK
        MOV     R1, WCNT
        ADD     #255., R1
        CLRB    R1
        SWAB    R1
        MOV     R1, (R4)        ; NUMBER OF SECTORS TO TRANSFER
; DIVIDE PBN BY 85
        MOV     PBN, REMNDR
        MOV     #10., DCNTR     ; COUNTER
        MOV     #125000, DIVSR  ; 85 SHIFTED TO THE LEFT END
        CALL    DIVC
; CYLINDER IS IN QUOT
        MOV     QUOT, 4(R4)
        SWAB    QUOT
        MOV     QUOT, 6(R4)
; DIVIDE REMNDR BY 17
        MOV     #3., DCNTR
        MOV     #000104, DIVSR  ; 17 SHIFTED LEFT TWICE
        CALL    DIVC
        MOV     QUOT, 10(R4)
        INC     REMNDR
        MOV     REMNDR, 2(R4)
; COMMAND AND NUMBER OF SECTORS DONE.
; SECTOR ADDRESS DONE.
; TIME TO SEND THE COMMAND
; ALSO THIS IS AN ENTRY POINT FOR RETRY

        MOVB    #02, @#ADXREG   ; SET INDEX REGISTER
        MOV     CBADDR, R2
        MOV     #ADACS0, R1
        MOV     #6., R0
        MOV     (R2)+, (R1)     ; TRANSFER TASK FILE
        SOB     R0, .-2

        TST     FLAGS
        BPL     30$             ; IF READ, BYPASS TO AWAIT INTERRUPT EXIT
; IF WRITE
; WAIT FOR DRQ
        MOVB    #17, @#ADXREG
        BITB    #010, @#ADACS0
        BEQ     .-6

        MOVB    #10, @#ADXREG
        MOV     #ADDMWC, R2
        MOV     #-256., (R2)
        MOV     #401, -(R2)     ; START DMA TRANSFER, NO DMA INTERRUPT EXPECTED
30$:
; EXIT TO MONITOR, AWAIT FOR ATA INTERRUPT.
; AT THIS POINT ATA CONTROLLER IS INSTRUCTED AND BUSY WITH THE JOB
        RTS             PC

; INTERRUPT SERVICE

.SBTTL  INTERRUPT SERVICE SECTION
.DRVTB  AD, AD$VEC, ADINT
.DRVTB  , DM$VEC, DMINT


.DRAST  AD, 4
; CHECK FOR ERRORS
        MOVB    #17, @#ADXREG
        MOV     @#ADACS0, R3
        BIT     #001, R3
        BNE     ERDONE
        MOV     #ADDMWC, R1
        TST     (R1)
        BNE     ERDONE
        MOVB    #10, @#ADXREG
        MOV     WCNT, R0
        TST     FLAGS
        BMI     10$
; READ SECTOR DONE, BUFFER IS TO TRANSFER

; WILL READ MORE?
        CMP     R0, #256.
        BHI     20$
; NO.
        MOV     #505, R2        ; DMA TRANSFER W/INTERRUPTS
        BR      25$             ; START DMA AND WAIT DMA INTERRUPT
       
; YES. TRANSFER CURRENT BUFFER WITH DMA INTERRUPTS DISABLED.
20$:    MOV     #256., R0
        SUB     R0, WCNT
        MOV     #405, R2        ; DMA TRANSFER NO INTERRUPTS
25$:    NEG     R0
        MOV     R0, (R1)
        MOV     R2, -(R1)       ; START DMA TRANSFER
        RTS     PC              ; WAIT FOR ATA INTERRUPT

10$:
; WRITE SECTOR DONE
; THE BUFFER TRANSFERRED, UPDATE WCNT
        SUB     #256., R0
        BPL     30$             ; CHECK IF IT WAS THE LAST SECTOR IN SERIES
        CLR     R0              ; THE LAST
30$:    MOV     R0, WCNT
        BEQ     CKDRQC
        BIT     #010, R3
        BEQ     ERDONE          ; DRQ SHOULD BE SET HERE

        MOV     #-256., (R1)
        MOV     #401, -(R1)     ; START DMA TRANSFER, NO DMA INTERRUPT EXPECTED
        RTS     PC              ; WAIT FOR ATA INTERRUPT
CKDRQC:
        MOVB    #17, @#ADXREG
        BIT     #010, @#ADACS0
        BNE     ERDONE          ; DRQ SHOULD BE CLEAR HERE
        BR      DONE

.DRAST  DM, 4
; FALL HERE UPON:
; - THE LAST DMA IN READ SERIES
; OR
; - FILLER DMA COMPLETION
; FILLER DMA?
        MOV     #ADDMCS, R1
        MOV     (R1), R0
        CLR     (R1)+
        TST     R0
        BMI     ERDONE          ; CHECK BUS ERROR
        TST     (R1)
        BNE     ERDONE          ; CHECK DMA COMPLETION
        MOV     WCNT, R0
        BEQ     CKDRQC          ; IT WAS FILLER DMA

; THE LAST DMA
        CLR     WCNT
        TSTB    R0
        BEQ     CKDRQC          ; NO FILLER REQUIRED
        BIS     #177400, R0
        MOV     R0, (R1)
        MOV     #501, -(R1)     ; START FILLER DMA
        RTS     PC              ; WAIT FOR DMA INTERRUPT


; I/O COMPLETION

.SBTTL  I/O COMPLETION SECTION

ERDONE:
; XXX RESET THE CONTROLLER
        MOV     ADCQE,R5        ;HARD ERROR, POINT TO QUEUE ELEMENT
        BIS     #HDERR$,@-(R5)  ;SET HARD ERROR STATUS IN CHANNEL
DONE:
ADEXIT:
.DRFIN  AD

; HANDLER SUBROUTINES
; DIVC DIVIDE BY CONSTANT
; USES 4 REGISTERS
; REMINDER REPLACES THE DIVIDEND
; TDIV 168 US

DIVC:
        CLR     QUOT
        BR      DENTRY

SR1:    ROR     DIVSR           ; C IS ZERO FROM ASL QUOT AT QUO1

DENTRY:
        SUB     DIVSR, REMNDR
        BLO     QUO0
        SEC
QUO1:
        ROL     QUOT
        SOB     DCNTR, SR1
        BR      DDONE

SR2:    ROR     DIVSR           ; C IS ZERO FROM ASL QUOT AT QUO0
        ADD     DIVSR, REMNDR
        BLO     QUO1            ; C IS SET IF BRANCH
QUO0:
        ASL     QUOT
        SOB     DCNTR, SR2
        ADD     DIVSR, REMNDR
DDONE:  RTS     PC

WCNT:   .WORD   0                       ;
CBADDR: .WORD   0
CMDBLK: .WORD   0               ; +0 SECTOR COUNT
        .WORD   0               ; +2 SECTOR NUMBER
        .WORD   0               ; +4 CYLINDER NUMBER LOW
        .WORD   0               ; +6 CYLINDER NUMBER HIGH
        .WORD   0               ; +10 DRIVE SELECT & HEAD NUMBER
        .WORD   0               ; +12 COMMAND

; BOOTSTRAP DRIVER

.SBTTL  BOOTSTRAP DRIVER
.DRBOT  AD,BOOT1,READ

        . = ADBOOT+40           ; PUT THE JUMP BOOT INTO SYSCOM AREA
BOOT1:  JMP     @#BOOT-ADBOOT   ; START THE BOOTSTRAP
        . = ADBOOT+210
; READS FROM THE DEVICE
; PARAMETERS:
; R0 BLOCK NUMBER
; R1 WORD COUNT
; R2 MEMORY BUFFER

; ATA REGS ALLOCATION
; +0 SECTOR COUNT
; +2 SECTOR NUMBER
; +4 CYLINDER NUMBER LOW
; +6 CYLINDER NUMBER HIGH
; +10 DRIVE SELECT & HEAD NUMBER
; +12 COMMAND


READ:
        MOVB    #02, @#ADXREG   ; SET INDEX REGISTER
        MOV     #ADACS0, R4     ; ATA CS0
        MOV     R1, R3          ; WCNT
        ADD     #255., R3
        CLRB    R3
        SWAB    R3
        MOV     R3, (R4)        ; +0, NUMBER OF SECTORS TO TRANSFER
; DIVIDE PBN IN R0 BY 85
        JSR     R4, BDIVC       ; R0 PBN
        .WORD   10.             ; DCNTR
        .WORD   125000          ; DIVSR 85 SHIFTED TO THE LEFT END
; CYLINDER IS IN R3, SAVE IT TO R5
        MOV     R5, R5
; DIVIDE REMNDR IN R0 BY 17
        JSR     R4, BDIVC
        .WORD   3.              ; DCNTR
        .WORD   000104          ; DIVSR 17 SHIFTED LEFT TWICE
; HEAD IS IN R3, SECTOR IS IN R0
        INC     R0              ; SECTOR NO STARTS WITH 1
        MOV     R0, (R4)        ; +2, SECTOR NO
        MOV     R5, (R4)        ; +4, CYLINDER LOW
        SWAB    R5
        MOV     R5, (R4)        ; +6, CYLINDER HIGH
        MOV     R3, (R4)        ; +10, HEAD NO

; NUMBER OF SECTORS DONE.
; SECTOR ADDRESS DONE.
; TIME TO SEND THE COMMAND
        MOV     #040, (R4)      ; +12, READ SECTORS COMMAND
; WAIT FOR DRQ
DRQWAI: MOVB    #17, @#ADXREG   ; SET INDEX REGISTER
        BIT     #010, (R4)
        BEQ     .-4
; CHECK FOR AN ERROR
        BIT     #001, (R4)
        BNE     RDERR

; READ DATA FROM BUFFER INTO MEMORY
1$:     MOVB    #07, @#ADXREG   ; SET INDEX REGISTER
        BIT     #010, (R4)
        BEQ     DRQWAI
        MOV     (R4), (R2)+
        SOB     R1, 1$
; EMPTY THE REST OF THE BUFFER
2$:     MOVB    #07, @#ADXREG   ; SET INDEX REGISTER
        BIT     #010, (R4)
        BEQ     RDONE
        CMP     (R4), (R4)
        BR      2$
RDONE:
        CLC
        RTS     PC
RDERR:
        JMP     @#<BIOERR-ADBOOT>


; DIVIDEND, REMINDER R0
; QUOT R3
; DIVSR (SP)
; DCNTR 2(SP)

BDIVC:
        CLR     R3
        MOV     (R4)+, -(SP)    ; DCNTR
        MOV     (R4)+, -(SP)    ; DIVSR
BDENTR:
        SUB     (SP)+, R0       ; _DIVSR_ -> DCNTR
        BLO     BQUO0
        SEC
BQUO1:  ROL     R3
        DEC     (SP)            ; _DCNTR_
        BEQ     BDDONE
        ROR     -(SP)           ; C IS ZERO FROM ASL R3 AT QUO1 DCNTR -> _DIVSR_
        BR      BDENTR

BSR:    ROR     -(SP)           ; C IS ZERO FROM ASL R3 AT QUO0  DCNTR -> _DIVSR_
        ADD     (SP)+, R0       ; _DIVSR_ -> DCNTR
        BLO     BQUO1           ; C IS SET IF BRANCH
BQUO0:
        ASL     R3
        DEC     (SP)            ; _DCNTR_
        BNE     BSR
        ADD     -(SP), R0       ; DCNTR -> _DIVSR_
        TST     (SP)+           ; _DIVSR_ -> DCNTR
BDDONE: TST     (SP)+           ; _DCNTR_ -> R4_SAV
        RTS     R4

.=ADBOOT+612

BOOT:   MOV     #10000,SP       ; SET UP THE STACK POINTER
        MOV     #2,R0           ; BLOCK NUMBER OF SECONDARY BOOTSTRAP
        MOV     #<4*256.>,R1    ; WORD COUNT OF 4 BLOCKS (2-5)
        MOV     #1000,R2        ; MEMORY ADDRESS OF SECONDARY BOOT (B$BOOT)
        CALL    READ                    ; LOAD THE SECONDARY BOOT
        MOV     #<READ-ADBOOT>,@#B$READ ; STORE POINTER TO READ ROUTINE
        MOV     #B$DNAM,@#B$DEVN        ; STORE RAD50 DEVICE NAME
        CLR     @#B$DEVU                ; STORE UNIT NUMBER (ALWAYS 0)
        JMP     @#B$BOOT                ; ENTER THE SECONDARY BOOT


; HANDLER TERMINATION

.SBTTL  HANDLER TERMINATION SECTION

.DREND  AD
.END


07 Aug 2018 05:24
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 47 posts ]  Go to page Previous  1, 2, 3, 4

Who is online

Users browsing this forum: No registered users and 14 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.