;*************************************
;
;  THESE ROUTINES WILL ALLOCATE THE FIRST
;  OR NEXT ALLOCATION
;
;*************************************
;
;  PRIMARY ALLOCATION
;  THIS ROUTINE IS CALLED TO ALLOCATE THE FIRST
;  SECTOR TO A FILE OR TO ALLOCATE
;  A SECTOR TO THE DIRECTORY
;
INTTS
NXTDS
 LDA #1
 LDX #0 ;BEGINNING ZONE
 STA NAHEAD ;EVERY OTHER SECTOR
 STX TRACK ;LAST ONE AT T&S 00
 STX SECTOR ;*
 BEQ HDGS1 ;JMP TO COMMON CODE
;
;  SECONDARY ALLOCATION
;  THIS ROUTINE IS CALLED TO ALLOCATE N SECTORS
;  TO AN EXISTING FILE OR IN THE CASE
;  THAT THE PRIMARY ALLOCATION ZONE
;  IS FULL AN ATTEMPT WILL BE MADE TO ALLOCATE
;  A SECTOR FROM THIS THE NON-PRIME ZONES
;
NXTTS
 LDX #10 ;N AHEAD = 10
 STX NAHEAD ;*
 LDX #1 ;BEGINNING ZONE NUMBER
;
;  THE FOLLOWING CODE IS COMMON TO BOTH
;
HDGS1
 STX HDTYP ;SAVE BEG ZONE = REQ TYPE
 STX HDCZN ;SAVE AS CURRENT ZONE ALSO
 LDX DRVNUM ;CHK IF VER FLAG SET
 LDA HDDFLG,X ;*
 AND #HDVIP ;*
 BEQ HDGS6 ;BR IF
 LDA #VERLK ;GIVE THE VALIDATE LOCK ERROR
 JSR CMDERR ;*
HDGS6
;****************************************
;
;  DO OPTIMUM ALLOCATION OF THE SECTOR
;
;****************************************
 LDA TRACK ;CURRENT TRACK #
 JSR HDGNSB ;GET # SECTORS THIS TRACK
 STA HDTMPA ;SAVE
 STA HDTMPB ;*
 LDA SECTOR ;CURRENT SECTOR
 AND #$3F ;TURN OFF HEAD BITS
 CLC ;ADD THE NUMBER AHEAD
 ADC NAHEAD ;*
 CMP HDTMPA ;CHK FOR WRAP
 BCC GS1 ;BR IF NO WRAP AROUND
 SEC ;CALC # WRAPPED
 SBC HDTMPA ;*
GS1
 STA HDTMPA ;SAVE DESIRED SECTOR #
 LDA SECTOR ;COPY PROPER HEAD BITS
 AND #$C0 ;*
 ORA HDTMPA ;*
 STA SECTOR ;*
 ;CALC # SECTORS TO SEARCH
 ;BETWEEN HERE AND END OF TRACK
 AND #$3F ;SECTOR # ONLY
 STA HDTMPA ;*
 SEC ;SUBTRACT FROM TOTAL ON TRK
 LDA HDTMPB
 SBC HDTMPA
 STA HDTMPA ;# TO END OF TRACK
 JSR SRCHET ;SEARCH TO END OF TRACK
 BEQ GS2 ;BR IF NOT FOUND
GSGOT
 RTS ;EXIT (NZ=GOT ONE)
GS2
 LDA HDTMPB ;SEARCH WHOLE TRK
 STA HDTMPA ;*
 LDA SECTOR ;*
 AND #$C0 ;BEG AT SECTOR 00
 STA SECTOR ;*
 JSR SRCHET ;LOOK FOR ONE
 BNE GSGOT ;BR IF FOUND ONE
;
;  COULD NOT FIND A SECTOR SO
;  GO BACK TO BEGINNING OF PROPER
;  ZONE AND LOOK TILL END OF DISK
;  FOR A SECTOR
;
;  NOW LOOK AT FULL SWITCHES TO SEE
;  IF DESIRED ZONE HAS AVAILABLE SECTORS
;
HDGS2
 LDX HDCZN ;GET DESIRED ZONE #
 JSR HDCIND ;CALC INDEX VALUE
 LDA HDZFUL,X ;LOOK AT FULL SW.
 BEQ HDGS4 ;JMP IF NOT FULL
HDGS3
 INC HDCZN ;BUMP TO NEXT ZONE
 LDX DRVNUM ;GET MAX ON THAT DRIVE
 LDA HDCZN ;CHK IF AT END OF MEDIA
 CMP HDNZA,X ;*
 BCC HDGS2 ;IF NOT GO CHK THAT ZONE
;
;  ZONES 1-N ARE FULL
;  TRY ZONE 0 UNLESS WE STARTED THERE
;
 DEC HDTYP ;CHK REQUEST TYPE
 LDA HDTYP ;SET PROPER ZONE
 STA HDCZN ;*
 BEQ HDGS2 ;GO GET FROM ZONE
;
;  GIVE DISK FULL ERROR
;
 LDA #DSKFUL ;ERROR MSG
 JMP CMDERR ;EXIT
;
; ALLOCATE A SECTOR FROM THE ZONE
; THE TABLE INDEX IS IN REG X
;
HDGS4
 JSR HDGTS ;GET A SECTOR
 BEQ HDGS5 ;JMP IF NONE ARE AVAIL
 STA SECTOR ;SAVE SECTOR #
 STY TRACK ;SAVE TRACK #
 RTS ;EXIT TO CALLER
;
;  ZONE IS FULLY ALLOCATED MARK IT & MOVE TO NEXT
;
HDGS5
 LDA #1 ;NZ IS FULL
 STA HDZFUL,X ;*
 BNE HDGS3 ;JMP
 .PAG 'GET A SECTOR'
;  GET A SECTOR FROM THE CALC ZONE INDEX
;
;  ON EXIT:
;    X=CALC ZONE # (UNCHANGED)
;    Z=NO SECTOR AVAILABLE
;    NZ=SECTOR IS ALLOC (SEE A&Y)
;    A=ALLOCATED SECTOR ADDR
;    Y=ALLOCATED TRACK ADDR
;
;  ON ENTRANCE:
;    HDCZN=UNCALCULATED ZONE #
;
HDGTS
 JSR HDISU ;SET UP INDIRECT WORD
 JSR HDLBM ;LOAD THE DESIGNATED BAM
 LDY #HDBIT1 ;PT TO FIRST BIT
HDGTS1
 LDA (HDBMP),Y ;LOOK AT NEXT GROUP OF SECTS.
 BNE HDGTS2 ;JMP IF ANY AVAILABLE
 INY ;BUMP TO NEXT GROUP
 BNE HDGTS1 ;LOOP TILL WHOLE BAM CHKD
;
;  NONE AVAILABLE IN THIS BAM
;
 RTS ;EXIT (Z IS SET)
;
;  FOUND SOME AVAILABLE
;  SO CALCULATE THE TRACK & SECTOR ADDR OF ONE OF THEM
;
;
;FIRST CALC THE BIT NUMBER
;
HDGTS2
 LDX #0 ;BIT 0 = LEFTMOST BIT
HDGTS4
 ASL A ;LOOK AT LEFTMOST
 BCS HDGTS3 ;BR IF BIT IS SET
 INX ;BUMP THE BIT NUMBER
 BNE HDGTS4 ;JMP
HDGTS3
 STX HDTMP1 ;SAVE THE BIT NUMBER
;
; TURN  THE BIT OFF TO INDICATE
; THAT THE SECTOR HAS BEEN ALLOCATED
;
HDGT4
 LSR A ;MOVE A ZERO BACK
 DEX ;KEEP SHIFTING ZEROES BACK IN
 BPL HDGT4 ;LOOP TILL DONE
;
;  PUT BYTE BACK INTO BAM
;
 STA (HDBMP),Y ;*
;
; CALCULATE THE BYTE NUMBER
;
 TYA ;BAM INDEX
 SEC ;PREP FOR SBC
 SBC #HDBIT1 ;INDEX TO FIRST BYTE
 STA HDTMP2 ;SAVE # BYTES
;
; MULTIPLY NUMBER OF BYTES BY 8
;
 LDA #0 ;CLEAR HIGH BYTE
 STA HDTMP3 ;*
 ASL HDTMP2 ;SHIFT LEFT 3
 ROL HDTMP3 ;*
 ASL HDTMP2 ;*
 ROL HDTMP3 ;*
 ASL HDTMP2 ;*
 ROL HDTMP3 ;*
;
; ADD IN THE NUMBER OF BITS
;
 LDA HDTMP1 ;*
 ADC HDTMP2 ;*
 STA HDTMP2
 BCC HDGT5 ;16 BIT ADD
 INC HDTMP3
;
;  HDTMP 2&3 ARE NOW EQ TO #BITS INTO BAM
;
HDGT5
;
;  GET # SECTORS PER CYLINDER
;
 LDY #HDNSEC ;NUMBER PER SURFACE
 LDA (HDBMP),Y ;*
 LDX DRVNUM ;DRIVE NUMBER
 PHA
 LDA HDNSUR,X ;GET NUMBER OF SURFACES
 AND #HDSURF ;LEAVE ONLY # SURFS
 TAY
 PLA
 DEY ;CHK FOR ONLY ONE SURFACE
 BEQ HDGT5A ;JMP IF ONLY ONE
 ASL A ;MULT # SECTORS * 2
 DEY ;CHK IF TWO SURFACES
 BEQ HDGT5A ;JMP IF TWO SURFACES
 ASL A ;MULTIPLIES THE # SECT * 4
HDGT5A
 STA HDTMP4 ;SAVE NUMBER OF SECTS. PER CYL
;
;  DIVIDE NUMBER OF BITS DISP INTO
;  BAM BY THE NUMBER OF SECTORS PER
;  CYLINDER TO GIVE THE CYLINDER
;  OFFSET FROM THE FIRST OF THE BAM
;  AND THE REMAINDER IS THE SECTOR WITHIN THE CYL
;
; (ACTUALLY MAX OF 11 BITS IN HDTMP2&3)
; 8 BITS IN HDTMP4&5
; RESULT GOES IN HDTMP1
;
 LDA #0 ;CLEAR HIGH RESULT
 STA HDTMP5 ;*
 STA HDTMP1 ;CLEAR RESULT
 LDA #2 ;SET SHIFT COUNTER INIT=2
 STA HDTMP ;*
;
;  ALIGN HIGH ORDER BITS
;
HDGT6
 ASL HDTMP4 ;SHIFT 8 LEFT
 INC HDTMP ;BUMP SHIFT COUNTER
 BCC HDGT6 ;ASSUMES NOT DIV BY 0
 ROL HDTMP5 ;SHIFT THREE MORE TIMES
 ASL HDTMP4 ;*
 ROL HDTMP5 ;*
 ASL HDTMP4 ;*
 ROL HDTMP5 ;*
;
;  NOW SUBTRACT SHIFTED DIVISOR FROM DIVIDEND
;
HDGT7
 SEC ;PREP FOR SBC
 LDA HDTMP2 ;LOW BYTE OF DIVIDEND
 SBC HDTMP4 ;LOW BYTE OF DIVISOR
 TAX ;DONT UPDATE YET
 LDA HDTMP3 ;HIGH BYTE DIVIDEND
 SBC HDTMP5 ;HIGH BYTE DIVISOR
 BCC HDGT8 ;BR IF RESULT WENT MINUS
 STA HDTMP3 ;ELSE UPDATE DIVIDEND
 STX HDTMP2 ;*
 INC HDTMP1 ;SET LOW BIT IN RESULT
 BNE HDGT7 ;JMP
;
;  SHIFT DIVISOR RIGHT
;
HDGT8
 LSR HDTMP5 ;*
 ROR HDTMP4 ;*
;
;  DECR SHIFT COUNTER
;
 DEC HDTMP ;*
 BMI HDGT9 ;JMP IF ALL DONE
;
;  SHIFT RESULT LEFT ONE
;
 ASL HDTMP1 ;*
 JMP HDGT7 ;LOOP TILL DONE
;
; DIVIDE DONE NOW CALC TRACK #
;
HDGT9
 LDY #HDCYL ;GET BEG CYL #
 LDA (HDBMP),Y ;*
 CLC ;PREP FOR ADC
 ADC HDTMP1 ;ADD QUOTIENT
 PHA ;SAVE TRACK (CYLINDER)
;
;  REMAINDER DIVIDED BY # SECTORS PER SURFACE = HEAD #
;
 LDY #HDNSEC ;PT TO # SECTS PER SURF
 LDA HDTMP2 ;REMAINDER FROM DIVIDE
 LDX #255 ;RESULT
HDGT10
 SEC ;PREP FOR SBC
 SBC (HDBMP),Y ;SUB LOOP
 INX ;*
 BCS HDGT10 ;LOOP TILL DONE
;
;  X = HEAD NUMBER
;
 ADC (HDBMP),Y ;MAKE POSITIVE
 ORA HDXLT,X ;OR HEAD INTO SECTOR #
 STA HDTMP ;SAVE HEAD & SECTOR
;
; MARK BAM AS MODIFIED & CALC NEW LRC
;
 JSR HDCLRC ;*
;
;
;  NOW DECREMENT # SECTORS AVAIL
;
 JSR HDDBC ;DO IT
;
; NOW RETURN NZ,A=SECTOR,Y=CYLINDER,X=INDEX
;
 PLA ;Y=CYLINDER (TRACK)
 TAY ;*
 LDX HDCZN ;ORIG ZONE
 JSR HDCIND ;CALC INDEX
 LDA HDTMP ;A=SECTOR (&HEAD)
 CMP #$FF ;SET NZ
 RTS ;EXIT TO CALLER
;
HDXLT .BYT 0,$40,$80,$C0 ;HEAD TRANSLATE
;
;   SEARCH FROM CURRENT T&S TO END OF TRACK
;
SRCHET
 JSR FINDTS ;SET POINTERS TO CURNT POS.
 LDX SECTOR ;SAVE SECTOR
 STX HDTMP1 ;*
 STA HDTMP2 ;SAVE BIT
SRCHE1
 LDA (HDBMP),Y ;GET THE BYTE
 BIT HDTMP2 ;TEST IF AVAILABLE
 BNE SRCHE3 ;BR IF AVAIL
 DEC HDTMPA ;DEC # SECTORS TO CHECK
 BEQ SRCHE2 ;BR IF DONE WITH SCAN
 INC HDTMP1 ;BUMP CURNT SECTOR
 ROR HDTMP2 ;MOVE MASK BIT TO THE RIGHT
 BNE SRCHE1 ;LOOP TILL DONE/FOUND
 ROR HDTMP2 ;PUT BIT BACK INTO BIT 7
 INY ;BUMP TO NEXT BYTE
 BNE SRCHE1 ;JMP
SRCHE2
 RTS ;EXIT NZ=FOUND Z=NOT FOUND
SRCHE3
 LDA HDTMP2 ;BIT MASK
 LDX HDTMP1
 STX SECTOR ;SECTOR TO USE
 JSR HDCBIK ;ALLOC SECTOR & GEN LRC
 LDA #1 ;NZ
 RTS
 .END
