1 title 'Requester Network I/O System for CP/NET 1.2' 2 page 54 3 4;*************************************************************** 5;*************************************************************** 6;** ** 7;** R e q u e s t e r N e t w o r k I / O S y s t e m ** 8;** ** 9;*************************************************************** 10;*************************************************************** 11 12;/* 13; Copyright (C) 1980, 1981, 1982 14; Digital Research 15; P.O. Box 579 16; Pacific Grove, CA 93950 17; 18; Revised: October 5, 1982 19; 20; Modified December 2006 for Z80SIM by Udo Munk 21;*/ 22 23false equ 0 24true equ not false 25 26cpnos equ false ; cp/net system 27 28always$retry equ false ; force continuous retries 29 30ASCII equ false 31 32debug equ false 33 34 CSEG 35 if cpnos 36 extrn BDOS 37 else 38BDOS equ 0005h 39 endif 40 41NIOS: 42 public NIOS 43; Jump vector for SNIOS entry points 44 jmp ntwrkinit ; network initialization 45 jmp ntwrksts ; network status 46 jmp cnfgtbladr ; return config table addr 47 jmp sendmsg ; send message on network 48 jmp receivemsg ; receive message from network 49 jmp ntwrkerror ; network error 50 jmp ntwrkwboot ; network warm boot 51 52slave$ID equ 11h ; slave processor ID number 53 54 if cpnos 55; Initial Slave Configuration Table 56Initconfigtbl: 57 db 0000$0000b ; network status byte 58 db slave$ID ; slave processor ID number 59 db 84h,0 ; A: Disk device 60 db 81h,0 ; B: " 61 db 82h,0 ; C: " 62 db 83h,0 ; D: " 63 db 80h,0 ; E: " 64 db 85h,0 ; F: " 65 db 86h,0 ; G: " 66 db 87h,0 ; H: " 67 db 88h,0 ; I: " 68 db 89h,0 ; J: " 69 db 8ah,0 ; K: " 70 db 8bh,0 ; L: " 71 db 8ch,0 ; M: " 72 db 8dh,0 ; N: " 73 db 8eh,0 ; O: " 74 db 8fh,0 ; P: " 75 db 0,0 ; console device 76 db 0,0 ; list device: 77 db 0 ; buffer index 78 db 0 ; FMT 79 db 0 ; DID 80 db slave$ID ; SID 81 db 5 ; FNC 82initcfglen equ $-initconfigtbl 83 endif 84 85defaultmaster equ 00h 86 87wboot$msg: ; data for warm boot routine 88 db '<Warm Boot>' 89 db '$' 90 91networkerrmsg: 92 db 'Network Error' 93 db '$' 94 95 page 96 DSEG 97 98; Slave Configuration Table 99configtbl: 100 101Network$status: 102 ds 1 ; network status byte 103 ds 1 ; slave processor ID number 104 ds 2 ; A: Disk device 105 ds 2 ; B: " 106 ds 2 ; C: " 107 ds 2 ; D: " 108 ds 2 ; E: " 109 ds 2 ; F: " 110 ds 2 ; G: " 111 ds 2 ; H: " 112 ds 2 ; I: " 113 ds 2 ; J: " 114 ds 2 ; K: " 115 ds 2 ; L: " 116 ds 2 ; M: " 117 ds 2 ; N: " 118 ds 2 ; O: " 119 ds 2 ; P: " 120 121 ds 2 ; console device 122 123 ds 2 ; list device: 124 ds 1 ; buffer index 125 db 0 ; FMT 126 db 0 ; DID 127 db Slave$ID ; SID (CP/NOS must still initialize) 128 db 5 ; FNC 129 ds 1 ; SIZ 130 ds 1 ; MSG(0) List number 131 ds 128 ; MSG(1) ... MSG(128) 132 133msg$adr: 134 ds 2 ; message address 135 136timeout$retries equ 100 ; timeout a max of 100 times 137max$retries equ 10 ; send message max of 10 times 138retry$count: 139 ds 1 140 141FirstPass: 142 db 0ffh 143 144; Network Status Byte Equates 145; 146active equ 0001$0000b ; slave logged in on network 147rcverr equ 0000$0010b ; error in received message 148senderr equ 0000$0001b ; unable to send message 149 150; General Equates 151; 152SOH equ 01h ; Start of Header 153STX equ 02h ; Start of Data 154ETX equ 03h ; End of Data 155EOT equ 04h ; End of Transmission 156ENQ equ 05h ; Enquire 157ACK equ 06h ; Acknowledge 158LF equ 0ah ; Line Feed 159CR equ 0dh ; Carriage Return 160NAK equ 15h ; Negative Acknowledge 161 162conout equ 2 ; console output function 163print equ 9 ; print string function 164rcvmsg equ 67 ; receive message NDOS function 165login equ 64 ; Login NDOS function 166 167; I/O Equates 168; 169stati equ 50 170mski equ 01 171dprti equ 51 172 173stato equ 50 174msko equ 02 175dprto equ 51 176 177 page 178 CSEG 179; Utility Procedures 180; 181 if ASCII 182Nib$out: ; A = nibble to be transmitted in ASCII 183 cpi 10 184 jnc nibAtoF ; jump if A-F 185 adi '0' 186 mov c,a 187 jmp Char$out 188nibAtoF: 189 adi 'A'-10 190 mov c,a 191 jmp Char$out 192 endif 193 194Pre$Char$out: 195 mov a,d 196 add c 197 mov d,a ; update the checksum in D 198 199nChar$out: ; C = byte to be transmitted 200 in stato 201 ani msko 202 jz nChar$out 203 204 mov a,c 205 out dprto 206 ret 207; 208Char$out: 209 call nChar$out 210 ret 211 212 if ASCII 213Nib$in: ; return nibble in A register 214 call Char$in 215 rc 216 ani 7fh 217 sui '0' 218 cpi 10 219 jc Nib$in$rtn ; must be 0-9 220 adi ('0'-'A'+10) and 0ffh 221 cpi 16 222 jc Nib$in$rtn ; must be 10-15 223 lda network$status 224 ori rcverr 225 sta network$status 226 mvi a,0 227 stc ; carry set indicating err cond 228 ret 229 230Nib$in$rtn: 231 ora a ; clear carry & return 232 ret 233 endif 234 235xChar$in: 236 mvi b,10 ; 100 ms corresponds to longest possible 237 jmp char$in0 ;wait between master operations 238 239Char$in: ; return byte in A register 240 ; carry set on rtn if timeout 241 mvi b,10 242Char$in0: 243 in stati ; busy wait forever, no reasonable 244 ani mski ; delay implemented yet 245 jz Char$in0 246Char$in1: 247; in stati 248; ani mski 249; jnz Char$in2 250; out delay 251; dcr b 252; jnz Char$in0 253; stc ; carry set for err cond = timeout 254; ret 255Char$in2: 256 in dprti 257 ret ; rtn with raw char and carry cleared 258 259Net$out: ; C = byte to be transmitted 260 ; D = checksum 261 mov a,d 262 add c 263 mov d,a 264 265 if ASCII 266 mov a,c 267 mov b,a 268 rar 269 rar 270 rar 271 rar 272 ani 0FH ; mask HI-LO nibble to LO nibble 273 call Nib$out 274 mov a,b 275 ani 0FH 276 jmp Nib$out 277 278 else 279 jmp Char$out 280 endif 281 282Msg$in: ; HL = destination address 283 ; E = # bytes to input 284 call Net$in 285 rc 286 mov m,a 287 inx h 288 dcr e 289 jnz Msg$in 290 ret 291 292Net$in: ; byte returned in A register 293 ; D = checksum accumulator 294 295 if ASCII 296 call Nib$in 297 rc 298 add a 299 add a 300 add a 301 add a 302 push psw 303 call Nib$in 304 pop b 305 rc 306 ora b 307 308 else 309 call Char$in ;receive byte in Binary mode 310 rc 311 endif 312 313chks$in: 314 mov b,a 315 add d ; add & update checksum accum. 316 mov d,a 317 ora a ; set cond code from checksum 318 mov a,b 319 ret 320 321Msg$out: ; HL = source address 322 ; E = # bytes to output 323 ; D = checksum 324 ; C = preamble byte 325 mvi d,0 ; initialize the checksum 326 call Pre$Char$out ; send the preamble character 327Msg$out$loop: 328 mov c,m 329 inx h 330 call Net$out 331 dcr e 332 jnz Msg$out$loop 333 ret 334 335 page 336; Network Initialization 337ntwrkinit: 338 if cpnos ; copy down network assignments 339 lxi h,Initconfigtbl 340 lxi d,configtbl 341 mvi c,initcfglen 342initloop: 343 mov a,m 344 stax d 345 inx h 346 inx d 347 dcr c 348 jnz initloop ; initialize config tbl from ROM 349 350 else 351 mvi a,slave$ID ;initialize slave ID byte 352 sta configtbl+1 ; in the configuration tablee 353 endif 354 355; device initialization, as required 356 if cpnos 357 call loginpr ; login to a master 358 endif 359 360initok: 361 xra a ; return code is 0=success 362 ret 363 364 365 page 366; Network Status 367ntwrksts: 368 lda network$status 369 mov b,a 370 ani not (rcverr+senderr) 371 sta network$status 372 mov a,b 373 ret 374 375; Return Configuration Table Address 376cnfgtbladr: 377 lxi h,configtbl 378 ret 379 380 page 381; Send Message on Network 382sendmsg: ; BC = message addr 383 mov h,b 384 mov l,c ; HL = message address 385 shld msg$adr 386re$sendmsg: 387 mvi a,max$retries 388 sta retry$count ; initialize retry count 389send: 390 lhld msg$adr 391 mvi c,ENQ 392 call Char$out ; send ENQ to master 393 mvi d,timeout$retries 394ENQ$response: 395 call Char$in 396 jnc got$ENQ$response 397 dcr d 398 jnz ENQ$response 399 jmp Char$in$timeout 400got$ENQ$response: 401 call get$ACK0 402 mvi c,SOH 403 mvi e,5 404 call Msg$out ; send SOH FMT DID SID FNC SIZ 405 xra a 406 sub d 407 mov c,a 408 call net$out ; send HCS (header checksum) 409 call get$ACK 410 dcx h 411 mov e,m 412 inx h 413 inr e 414 mvi c,STX 415 call Msg$out ; send STX DB0 DB1 ... 416 mvi c,ETX 417 call Pre$Char$out ; send ETX 418 xra a 419 sub d 420 mov c,a 421 call Net$out ; send the checksum 422 mvi c,EOT 423 call nChar$out ; send EOT 424 call get$ACK ; (leave these 425 ret ; two instructions) 426 427get$ACK: 428 call Char$in 429 jc send$retry ; jump if timeout 430get$ACK0: 431 ani 7fh 432 sui ACK 433 rz 434send$retry: 435 pop h ; discard return address 436 lxi h,retry$count 437 dcr m 438 jnz send ; send again unles max retries 439Char$in$timeout: 440 mvi a,senderr 441 442 if always$retry 443 call error$return 444 jmp re$sendmsg 445 else 446 jmp error$return 447 endif 448 449 page 450; Receive Message from Network 451receivemsg: ; BC = message addr 452 mov h,b 453 mov l,c ; HL = message address 454 shld msg$adr 455re$receivemsg: 456 mvi a,max$retries 457 sta retry$count ; initialize retry count 458re$call: 459 call receive ; rtn from receive is receive error 460 461receive$retry: 462 lxi h,retry$count 463 dcr m 464 jnz re$call 465receive$timeout: 466 mvi a,rcverr 467 468 if always$retry 469 call error$return 470 jmp re$receivemsg 471 else 472 jmp error$return 473 endif 474 475receive: 476 lhld msg$adr 477 mvi d,timeout$retries 478receive$firstchar: 479 call xcharin 480 jnc got$firstchar 481 dcr d 482 jnz receive$firstchar 483 pop h ; discard receive$retry rtn adr 484 jmp receive$timeout 485got$firstchar: 486 ani 7fh 487 cpi ENQ ; Enquire? 488 jnz receive 489 490 mvi c,ACK 491 call nChar$out ; acknowledge ENQ with an ACK 492 493 call Char$in 494 rc ; return to receive$retry 495 ani 7fh 496 cpi SOH ; Start of Header ? 497 rnz ; return to receive$retry 498 mov d,a ; initialize the HCS 499 mvi e,5 500 call Msg$in 501 rc ; return to receive$retry 502 call Net$in 503 rc ; return to receive$retry 504 jnz bad$checksum 505 call send$ACK 506 call Char$in 507 rc ; return to receive$retry 508 ani 7fh 509 cpi STX ; Start of Data ? 510 rnz ; return to receive$retry 511 mov d,a ; initialize the CKS 512 dcx h 513 mov e,m 514 inx h 515 inr e 516 call msg$in ; get DB0 DB1 ... 517 rc ; return to receive$retry 518 call Char$in ; get the ETX 519 rc ; return to receive$retry 520 ani 7fh 521 cpi ETX 522 rnz ; return to receive$retry 523 add d 524 mov d,a ; update CKS with ETX 525 call Net$in ; get CKS 526 rc ; return to receive$retry 527 call Char$in ; get EOT 528 rc ; return to receive$retry 529 ani 7fh 530 cpi EOT 531 rnz ; return to receive$retry 532 mov a,d 533 ora a ; test CKS 534 jnz bad$checksum 535 pop h ; discard receive$retry rtn adr 536 lhld msg$adr 537 inx h 538 lda configtbl+1 539 sub m 540 jz send$ACK ; jump with A=0 if DID ok 541 mvi a,0ffh ; return code shows bad DID 542send$ACK: 543 push psw ; save return code 544 mvi c,ACK 545 call nChar$out ; send ACK if checksum ok 546 pop psw ; restore return code 547 ret 548 549bad$DID: 550bad$checksum: 551 mvi c,NAK 552 jmp Char$out ; send NAK on bad chksm & not max retries 553; ret 554 555error$return: 556 lxi h,network$status 557 ora m 558 mov m,a 559 call ntwrkerror ; perform any required device re-init. 560 mvi a,0ffh 561 ret 562 563ntwrkerror: 564 ; perform any required device 565 ret ; re-initialization 566 567 page 568; 569ntwrkwboot: 570 571; This procedure is called each time the CCP is 572; reloaded from disk. This version prints "<WARM BOOT>" 573; on the console and then returns, but anything necessary 574; for restart can be put here. 575 576 mvi c,9 577 lxi d,wboot$msg 578 jmp BDOS 579 580 page 581 if cpnos 582; 583; LOGIN to a Master 584; 585; Equates 586; 587buff equ 0080h 588 589readbf equ 10 590 591active equ 0001$0000b 592 593loginpr: 594 mvi c,initpasswordmsglen 595 lxi h,initpasswordmsg 596 lxi d,passwordmsg 597copypassword: 598 mov a,m 599 stax d 600 inx h 601 inx d 602 dcr c 603 jnz copypassword 604 mvi c,print 605 lxi d,loginmsg 606 call BDOS 607 mvi c,readbf 608 lxi d,buff-1 609 mvi a,50h 610 stax d 611 call BDOS 612 lxi h,buff 613 mov a,m ; get # chars in the command tail 614 ora a 615 jz dologin ; default login if empty command tail 616 mov c,a ; A = # chars in command tail 617 xra a 618 mov b,a ; B will accumulate master ID 619scanblnks: 620 inx h 621 mov a,m 622 cpi ' ' 623 jnz pastblnks ; skip past leading blanks 624 dcr c 625 jnz scanblnks 626 jmp prelogin ; jump if command tail exhausted 627pastblnks: 628 cpi '[' 629 jz scanMstrID 630 mvi a,8 631 lxi d,passwordmsg+5+8-1 632 xchg 633spacefill: 634 mvi m,' ' 635 dcx h 636 dcr a 637 jnz spacefill 638 xchg 639scanLftBrkt: 640 mov a,m 641 cpi '[' 642 jz scanMstrID 643 inx d 644 stax d ;update the password 645 inx h 646 dcr c 647 jnz scanLftBrkt 648 jmp prelogin 649scanMstrID: 650 inx h 651 dcr c 652 jz loginerr 653 mov a,m 654 cpi ']' 655 jz prelogin 656 sui '0' 657 cpi 10 658 jc updateID 659 adi ('0'-'A'+10) and 0ffh 660 cpi 16 661 jnc loginerr 662updateID: 663 push psw 664 mov a,b 665 add a 666 add a 667 add a 668 add a 669 mov b,a ; accum * 16 670 pop psw 671 add b 672 mov b,a 673 jmp scanMstrID 674 675prelogin: 676 mov a,b 677 678dologin: 679 lxi b,passwordmsg+1 680 stax b 681 dcx b 682 call sendmsg 683 inr a 684 lxi d,loginfailedmsg 685 jz printmsg 686 lxi b,passwordmsg 687 call receivemsg 688 inr a 689 lxi d,loginfailedmsg 690 jz printmsg 691 lda passwordmsg+5 692 inr a 693 jnz loginOK 694 jmp printmsg 695 696loginerr: 697 lxi d,loginerrmsg 698printmsg: 699 mvi c,print 700 call BDOS 701 jmp loginpr ; try login again 702 703loginOK: 704 lxi h,network$status ; HL = status byte addr 705 mov a,m 706 ori active ; set active bit true 707 mov m,a 708 ret 709 710; 711; Local Data Segment 712; 713loginmsg: 714 db cr,lf 715 db 'LOGIN=' 716 db '$' 717 718initpasswordmsg: 719 db 00h ; FMT 720 db 00h ; DID Master ID # 721 db slave$ID ;SID 722 db 40h ; FNC 723 db 7 ; SIZ 724 db 'PASSWORD' ; password 725initpasswordmsglen equ $-initpasswordmsg 726 727 728loginerrmsg: 729 db lf 730 db 'Invalid LOGIN' 731 db '$' 732 733loginfailedmsg: 734 db lf 735 db 'LOGIN Failed' 736 db '$' 737 738 DSEG 739passwordmsg: 740 ds 1 ; FMT 741 ds 1 ; DID 742 ds 1 ; SID 743 ds 1 ; FNC 744 ds 1 ; SIZ 745 ds 8 ; DAT = password 746 endif 747 748 end 749