Mercurial > hg > Members > kono > nitros9-code
annotate level2/modules/pipeman_named.asm @ 1904:fd159d660df5
Changes for cobber
author | afra |
---|---|
date | Thu, 03 Nov 2005 01:37:41 +0000 |
parents | 46c68f878889 |
children | ac2f5aa71f93 |
rev | line source |
---|---|
0 | 1 ******************************************************************** |
2 * PipeMan - OS-9 Level Two Named Pipe File Manager | |
3 * | |
4 * $Id$ | |
5 * | |
1348 | 6 * Edt/Rev YYYY/MM/DD Modified by |
7 * Comment | |
0 | 8 * ------------------------------------------------------------------ |
1348 | 9 * 1986/02/23 Kent D. Meyers |
10 * Pipeman Modified to Include the SS.Ready I$GETSTT Call. | |
11 * | |
12 * 1986/03/26 Kent D. Meyers | |
13 * Major Bug Corrected. | |
14 * | |
15 * 1988/06/29 Kent D. Meyers | |
16 * Upgraded to Level II version. | |
17 * | |
18 * 1988/11/11 Chris J. Burke | |
19 * Added new labels and special defs. | |
20 * Added code to detect EOF in SS.Ready | |
21 * Reformatted to make the module easier to understand during coding. | |
22 * | |
23 * 1988/12/03 Chris J. Burke | |
24 * Added named pipes, etc for Level 2 upgrade, includes SS.SSig, | |
25 * SS.Relea, SS.Attr, SS.FD | |
26 * | |
27 * 1 1988/12/26 Chris J. Burke | |
28 * Release 1.0 for Tandy CoCo OS-9. | |
0 | 29 |
30 nam PipeMan | |
31 ttl OS9 Level Two Named Pipe File Manager | |
32 | |
33 * | |
34 * Copyright 1981, 1985, 1986, 1988 by Microware Systems Corporation | |
35 * All Rights Reserved | |
36 * | |
37 * Named pipe code by Burke & Burke. | |
38 * All rights assigned to Microware Systems Corporation. | |
39 * | |
40 * This file contains proprietary information of Microware Systems | |
41 * Corporation. Persons accessing this file will be held strictly | |
42 * accountable for their use of the information herein. | |
43 * | |
44 | |
45 * | |
46 * PIPEMAN | |
47 * | |
48 * Pipe File Manager | |
49 * | |
50 * WARNING | |
51 * ------- | |
52 * | |
53 * Opening an existing named pipe emulates IOMan's I$Close and | |
54 * I$Dup calls. This file manager contains subroutines that | |
55 * mimic the current operation of IOMan. Any changes to IOMan's | |
56 * FMEXEC, I$Close or I$Dup calls must also be made to this code. | |
57 * | |
58 * Device Driver Static Storage Layout | |
59 * ----------------------------------- | |
60 * | |
61 * $00-$01 V.List Pointer in system map to pipe buffer for 1st | |
62 * pipe (16 bits). | |
63 * | |
64 * Pipe Buffer Data Structure | |
65 * -------------------------- | |
66 * | |
67 * $00-$01 PP.PD Pointer to shared path descriptor | |
68 * $02-$03 PP.Next Pointer to next pipe buffer in system map | |
69 * $04-$05 PP.Prev Pointer to previous pipe buffer in system map | |
70 * $06-$07 PP.Rsv2 Reserved | |
71 * | |
72 * $08 PP.Data Data buffer begins at this offset | |
73 * | |
74 * Path Descriptor Data Structure | |
75 * ------------------------------ | |
76 * | |
77 * $00 PD.PD Path number | |
78 * $01 PD.MOD Access permissions | |
79 * $02 PD.CNT Number of open images (e.g. I$DUP) | |
80 * $05 PD.CPR Current process ID | |
81 * $06-$07 PD.RGS Address of caller's register stack | |
82 * $08-$09 PD.BUF System space pipe buffer base pointer | |
83 *** PP.Read must have bit 4 clear; PP.Writ must be PP.Read XOR 4 | |
84 * $0A PD.Read No bytes -- offset only | |
85 * $0A PD.RPID Process ID of reader waiting on signal | |
86 * $0B PD.RCT Number of blocked readers | |
87 * $0C PD.RSIG Signal to send reader | |
88 * $0D PD.REOR Read EOR character | |
89 * $0E PD.Writ No bytes -- offset only | |
90 * $0E PD.WPID Process ID of writer waiting on signal | |
91 * $0F PD.WCT Number of blocked writers | |
92 * $10 PD.WSIG Signal to send writer | |
93 * $11 PD.WEOR Write EOR character (dummy) | |
94 *** End of special section | |
95 * $12-$13 PD.End Pointer to end of pipe buffer | |
96 * $14-$15 PD.NxtI Next in pointer | |
97 * $16-$17 PD.NxtO Next out pointer | |
98 * $18 PD.RFlg "Ready" flag | |
99 * $19 PD.Wrtn "Written" flag | |
100 * $1A-$1B PD.BCnt # queue elements currently bufered | |
101 * $1C PD.Own Process ID of pipe original creator | |
102 * $1D PD.Keep Non-zero if this pipe has been kept open artificially | |
103 * $1E-$1F PD.QSiz Max. size of queue (in elements) | |
104 * . | |
105 * . | |
106 * $20 PD.DTP Device type $02 = PIPE | |
107 * $21 PD.ESiz Size of each queue element | |
108 * $22-$23 PD.ECnt Max. elements in queue | |
109 * $23-$3F PD.Name Pipe name (after moving PD.ECnt to PD.QSiz) | |
110 * | |
111 | |
112 page | |
113 * | |
114 * Global equates | |
115 * | |
116 ifp1 | |
117 use defsfile | |
508
02a8ba2b9092
Added headers to most source files, added clock2_bb.asm
boisy
parents:
0
diff
changeset
|
118 use pipedefs |
0 | 119 endc |
120 | |
121 * | |
122 * Local Equates | |
123 * | |
124 | |
125 XVER equ 3 ;Version | |
126 | |
127 * ASCII CONTROL CHARACTERS | |
128 | |
129 CR equ $0D | |
130 | |
131 * CONDITION CODES | |
132 | |
133 * PIPEMAN SPECIAL OFFSETS. | |
134 | |
135 PM.CPR equ PD.RPID-PD.READ | |
136 PM.CNT equ PD.RCT-PD.READ | |
137 PM.SIG equ PD.RSIG-PD.READ | |
138 PM.EOR equ PD.REOR-PD.READ | |
139 | |
140 * IOMAN special offsets. | |
141 * | |
142 * This constant is IOMAN release-dependent. | |
143 * It is the number of bytes between the entry stack | |
144 * pointer and the stacked PD pointer saved by *IOMAN*. | |
145 * Currently, the stack looks like this: | |
146 * | |
147 * A PL | |
148 * 9 PH <IOMAN post-SOPEN return address> | |
149 * 8 UL | |
150 * 7 UH | |
151 * 6 YL + | |
152 * 5 YH <PD pointer saved by IOMAN> | |
153 * 4 XL | |
154 * 3 XH | |
155 * 2 A | |
156 * 1 PL | |
157 * SP-> 0 PH <post OPEN/CREATE return address> | |
158 * <start of stack to be used by PIPEMAN> | |
159 | |
160 IOMAGIC equ 5 ;5 bytes to PD pointer | |
161 | |
162 * Local pipe buffer equates | |
163 | |
164 CInit equ %00100000 ;Set this bit to override PD queue parameters | |
165 | |
166 * Conditional assembly | |
167 | |
168 ANON set 0 ;Anonymous pipes only | |
169 NAMED set 1 ;Anonymous and named pipes | |
170 MSGS set 2 ;Both types of pipes, and message queues | |
171 WIZBANG set NAMED ;What features are we providing? | |
172 | |
173 NODIR set 0 ;Don't allow DIR on pipe devices | |
174 YESDIR set 1 ;Allow DIR on pipe devices | |
175 PIPEDIR set YESDIR ;Does DIR work on pipes? | |
176 | |
177 SLOWPD set 0 ;Slow PD location algorithm | |
178 QUICKPD set 1 ;Fast PD location algorithm | |
179 PDALGO set QUICKPD ;How to convert PD to system path # | |
180 | |
181 RECKLES set 0 ;Don't check for certain errors | |
182 CAREFUL set 1 ;Check for certain errors | |
183 CAUTION set CAREFUL | |
184 | |
185 page | |
186 * | |
187 * Module Header | |
188 * | |
189 | |
190 edition set 1 | |
191 | |
192 mod MODSIZE,MODNAM,FlMgr+Objct,ReEnt+XVER,JmpTbl,$0000 | |
193 | |
194 * Module Name | |
195 | |
196 MODNAM fcs "PipeMan" | |
197 fcb edition | |
198 | |
199 * Jump table | |
200 | |
201 JmpTbl lbra Create | |
202 lbra Open | |
203 lbra MakDir | |
204 lbra ChgDir | |
205 lbra Delete | |
206 lbra Seek | |
207 lbra Read | |
208 lbra Write | |
209 lbra ReadLn | |
210 lbra WriteLn | |
211 lbra GetStt | |
212 lbra SetStt | |
213 lbra Close | |
214 | |
215 page | |
216 * | |
217 * Create a named or anonymous pipe | |
218 * | |
219 * The size of the queue is determined by examining | |
220 * the path descriptor, since this information has | |
221 * been copied there from the device descriptor. | |
222 * | |
223 * Reg-U points to stacked registers of user. | |
224 * Reg-Y points to path descriptor | |
225 * | |
226 * If success, carry clear and X points to pipe buffer | |
227 * | |
228 | |
229 * Create function allows user to override both element | |
230 * count and element size. Override is enabled if if bit | |
231 * 5 of the access mode is set. For override, if MS bit | |
232 * of Reg-Y is clear, just use Reg-Y as queue element | |
233 * count. If MS bit of Reg-Y is set, use LS byte of | |
234 * Reg-Y as element size ($00 = no change) and bottom 7 | |
235 * bits of MS byte of Reg-Y as element count ($00 = no change) | |
236 | |
237 Create equ * | |
238 | |
239 lda R$A,U ;Get access mode | |
240 bita #CInit | |
241 beq Open | |
242 | |
243 * Handle queue size override | |
244 | |
245 ldd R$Y,U ;Get queue size initializer | |
246 bpl SetCnt ; (branch if just setting count) | |
247 | |
248 * Set element size and count | |
249 | |
250 tstb | |
251 beq Creat00 ; (branch if using default size) | |
252 | |
253 stb PD.ESiz,Y ;Reg-B = size of each element | |
254 | |
255 Creat00 anda #$7F | |
256 beq Open ; (branch if using default count) | |
257 | |
258 tfr a,B | |
259 clra | |
260 | |
261 * Set number of elements in queue from Reg-D | |
262 | |
263 SetCnt std PD.ECnt,Y ;Reg-D = number of elements | |
264 | |
265 * Enter here for normal OPEN | |
266 | |
267 Open equ * | |
268 | |
269 * Move number of elements in queue to make room for name | |
270 | |
271 ldd PD.ECnt,Y | |
272 std PD.QSiz,Y | |
273 | |
274 * Parse pathname | |
275 | |
276 clrb ;Assume anonymous pipe | |
277 clra ;Assume not 1st pipe | |
278 ldx R$X,U ;Point at file name in user's space | |
279 pshs U,Y,X,D ;Save file name, PD, reg. base, 1st & anon flag | |
280 | |
281 * Caller's Regs Ptr | |
282 * PD Ptr | |
283 * Path name uptr | |
284 * Named flag | |
285 * SP-> First flag | |
286 | |
287 os9 F$PrsNam ;Error if driver name (e.g. /pipe) invalid | |
288 bcs BadName | |
289 | |
290 * See if named or anonymous pipe requested. | |
291 | |
292 lbsr GtNext ;Return CC=MI if at end of path name | |
293 cmpa #'/ | |
294 beq HasName | |
295 | |
296 * /pipe____ | |
297 * X Y | |
298 * Pipe is anonymous -- set up dummy name in PD. | |
299 * Stack must match the named pipe setup | |
300 | |
301 NotName tfr Y,X ;Skip any trailing blanks | |
302 os9 F$PrsNam ; (should return carry set) | |
303 ldd #1 ;Length of dummy name | |
304 pshs Y,X,D | |
305 | |
306 ldy 10,S ;Get PD pointer | |
307 clr PD.Name,Y ; and set dummy name | |
308 | |
309 bra GoCheck | |
310 | |
311 * /pipe/foo____ | |
312 * X Y | |
313 * Pipe is named -- check length and flag on stack | |
314 | |
315 HasName tfr Y,X | |
316 os9 F$PrsNam ;Scan off the name | |
317 bcs BadName | |
318 | |
319 cmpb #NameMax ;Check length of name | |
320 bhi BadName | |
321 | |
322 * Length OK. X points to start of name, Y to end of name, | |
323 * B has name length. | |
324 * Save registers & length, and do final parse to skip white | |
325 | |
326 com 1,S ;Set "named" flag | |
327 clra | |
328 pshs Y,X,D | |
329 | |
330 tfr Y,X | |
331 os9 F$PrsNam ;Error if trying for pipe subdirectory | |
332 bcc BadNam2 | |
333 | |
334 * /pipe/foo____ | |
335 * X Y | |
336 * Need to get the pipe name into our address space | |
337 * Use the PD for a temporary buffer. | |
338 | |
339 NameOK ldx <D.Proc ;Pointer to caller's PD | |
340 lda P$Task,X ; get caller's DAT image # | |
341 ldx <D.SysPrc ;Pointer to our PD | |
342 ldb P$Task,X ; get system's DAT image # | |
343 ldy 0,S ;Byte count | |
344 ldx 2,S ;Source address | |
345 ldu 10,S ;Get PD pointer and convert to . . . | |
346 leau PD.Name,U ;Destination address | |
347 lbsr MovSet ;Move block, set MSB of last byte. | |
348 | |
349 * Wow! Everybody's in the same address space now. | |
350 | |
351 * Since this is a named pipe, force mode to UPDATE. | |
352 * Also, do not permit DIR. access | |
353 | |
354 ldx 10,S | |
355 lda PD.MOD,X | |
356 bita #DIR. | |
357 bne BadNam2 | |
358 | |
359 ora #(READ.+WRITE.) | |
360 sta PD.MOD,X | |
361 | |
362 * See if this is an existing pipe. To do this, we | |
363 * must get the linked list head pointer from the | |
364 * device driver's static storage. | |
365 * | |
366 * Stack looks like this: | |
367 * | |
368 * C 2 Sysmap Reg Pointer | |
369 * A 2 Sysmap PD Pointer | |
370 * 8 2 Usrmap Path name pointer | |
371 * 7 1 Named pipe flag | |
372 * 6 1 First pipe flag | |
373 * 4 2 Usrmap Pipe name end pointer | |
374 * 2 2 Usrmap Pipe name start pointer | |
375 * 0 2 Name length | |
376 * sp-> | |
377 | |
378 GoCheck ldx 10,S ;Get PD pointer | |
379 ldx PD.DEV,X ;Get device table pointer | |
380 ldu V$Stat,X ;Get static storage pointer | |
381 ldx V.List,U ;Get pointer to head of pipe bfr linked list | |
382 bne Not1st ; (reg-X = $0000 if no previous pipes) | |
383 | |
384 * This is the 1st pipe for this descriptor. | |
385 * Reg-X = $0000 | |
386 * Set flag and process as a new pipe. | |
387 | |
388 com 6,S ;This is the first pipe | |
389 bra NewPipe ;This is a new pipe | |
390 | |
391 * No time like the present for some error handlers | |
392 | |
393 * Generic error, cleaning stack | |
394 | |
395 BadXit2 leas 8,S | |
396 coma ;Set carry | |
397 rts | |
398 | |
399 * Bad Pathname -- 2 versions, depending on | |
400 * how much junk is on the stack. | |
401 | |
402 BadNam2 leas 6,S ;Clean stack | |
403 BadName ldb #E$BPNam | |
404 bra BadXit2 | |
405 | |
406 * Not Enough System RAM | |
407 | |
408 TooBig ldb #E$NoRAM | |
409 BadExit leas 6,S ;Clean stack | |
410 bra BadXit2 | |
411 | |
412 * Look up the pipe name, unless the pipe is anonymous. | |
413 * | |
414 * Reg-U points to driver static storage. | |
415 * Reg-X points to next pipe buffer to check. | |
416 | |
417 Not1st tst 7,S ;Unnamed pipes are always new | |
418 beq NewPipe | |
419 | |
420 ldy 10,S ;point at PD | |
421 leay PD.Name,Y ; then point at name in PD | |
422 | |
423 * Main loop. Always at least 1 pipe buffer to check first time through. | |
424 * Reg-X points to buffer to check, or $0000 if none. | |
425 * Reg-Y points to desired pipe name. | |
426 | |
427 ChkLoop pshs X | |
428 ldx PP.PD,X ;Point at PD for this pipe buffer | |
429 leax PD.Name,X ; and then point at name stored in PD | |
430 lbsr Compare | |
431 puls X | |
432 lbeq OldPipe ; (got a match) | |
433 | |
434 ldd PP.Next,X ;Don't fall off the edge | |
435 beq NewPipe ; (end of list) | |
436 | |
437 tfr D,X ;Advance to next buffer | |
438 bra ChkLoop | |
439 | |
440 * Pipe name not found. Create a new pipe. | |
441 * | |
442 * Reg-U points to driver static storage. | |
443 * Reg-X points to last pipe buffer checked ($0000 if 1st pipe) | |
444 | |
445 NewPipe ldy 10,S ;Get PD pointer | |
446 | |
447 ifeq (PIPEDIR-YESDIR) | |
448 lda PD.MOD,Y ;Check pipe attributes | |
449 bita #DIR. | |
450 beq NEWP1 | |
451 | |
452 * Initialize pipe characteristics for DIR. bit set | |
453 | |
454 lbsr SizDirP | |
455 * beq XYZZY ;Special if no pipes created | |
456 endc | |
457 | |
458 * Normal (non-dir) processing | |
459 | |
460 NewP1 ldd PD.QSiz,Y ;Get max element count | |
461 bne DoNew ; (graceful operation if no count) | |
462 | |
463 * Default pipe parameters if none in PD. | |
464 | |
465 ldd #$0100 ;Assume 256 byte buffer, 1 byte element | |
466 sta PD.ESiz,Y ;Reg-A = 1 | |
467 subd #PP.Data ;Compute elements for total size = 256 | |
468 std PD.QSiz,Y Use parameters in PD | |
469 | |
470 DoNew lbsr ECtoBC ;Convert element count to byte count in D | |
471 bcs TooBig ; (carry set if too big) | |
472 | |
473 * Carry has exit status | |
474 * Reg-D = # bytes for queue, w/o overhead | |
475 * Reg-X = previous buffer | |
476 * Reg-U = driver static storage | |
477 | |
478 tfr U,Y ;Save static storage pointer | |
479 | |
480 addd #PP.Data ;Add in overhead | |
481 bcs TooBig | |
482 | |
483 pshs D ;Save buffer size | |
484 os9 F$SrqMem ;Attempt to allocate buffer | |
485 puls D ;Recover size, clean stack, lose error msg | |
486 bcs TooBig | |
487 | |
488 * Found enough memory for pipe buffer. | |
489 * | |
490 * Pointer in Reg-U | |
491 * Size in Reg-D | |
492 * Previous buffer in Reg-X. | |
493 * Driver static storage in Reg-Y. | |
494 * | |
495 * Initialize the buffer | |
496 | |
497 pshs U,D ;Save buffer pointer & size | |
498 | |
499 * Clear pipe buffer header | |
500 | |
501 ldb #PP.Data ;Size of header | |
502 ClrBuf clr ,U+ | |
503 decb | |
504 bne ClrBuf | |
505 | |
506 puls D,U | |
507 | |
508 * Initialize path descriptor and other fields of pipe buffer | |
509 * for new pipe. | |
510 * | |
511 * Pointer in Reg-U | |
512 * Size in Reg-D | |
513 * Previous buffer in Reg-X. | |
514 * Driver static storage in Reg-Y. | |
515 * | |
516 * IOMan has already prefilled the PD to $00 and | |
517 * has set PD.CNT for this path to 1. | |
518 | |
519 pshs Y,X ;Save static storage pointer & prev.buff | |
520 | |
521 ldy (4+10),S ;Get PD pointer to Reg-Y | |
522 sty PP.PD,U ;Save pointer to PD in pipe buffer | |
523 | |
524 leax D,U ;Point to end of pipe.buff + 1 | |
525 stx PD.End,Y | |
526 | |
527 leax PP.Data,U ;Initial Next in & Next out pointers | |
528 stx PD.NxtI,Y | |
529 stx PD.NxtO,Y | |
530 | |
531 ldx <D.Proc ;Save ID of original creator | |
532 lda P$ID,X | |
533 sta PD.Own,Y | |
534 | |
535 puls Y,X ;Recover static storage pointer and prev.buff | |
536 | |
537 stx PP.Prev,U ;Save address of previous buffer ($0 if none) | |
538 bne LinkIn ; (branch if this isn't the 1st pipe) | |
539 | |
540 * Special -- this is the first pipe. | |
541 * Set PP.Next to $0000 and store buffer address in device memory. | |
542 * | |
543 * Reg-U = pointer to new buffer. | |
544 * Reg-X = $0000. | |
545 * Reg-Y = static storage | |
546 | |
547 ** Zero prefill of PP header covers this | |
548 ** stx PP.Next,U ;No next buffer | |
549 ** stx PP.Prev,U ;No previous buffer | |
550 stu V.List,Y ;Point driver static at this buffer | |
551 bra IsAsOld | |
552 | |
553 * There are other named pipes. Link this one in correctly | |
554 * after the last one checked. | |
555 * | |
556 * Reg-U = pointer to new buffer. | |
557 * Reg-X = Pointer to previous buffer. | |
558 * Reg-Y = static storage. | |
559 | |
560 LinkIn ldd PP.Next,X ;Get old's next (could be $0000) | |
561 stu PP.Next,X ;Set old's next pointing at new | |
562 std PP.Next,U ;Set new's next where old's was | |
563 stx PP.Prev,U ;Set new's prev pointing at old | |
564 pshs X,D | |
565 ldx 0,S ;Point X at original old's next | |
566 beq Link9 ; (branch if no next -- $0000 set already) | |
567 stu PP.Prev,X ;Set prev of old's original next to new | |
568 Link9 puls D,X | |
569 | |
570 * Now we look pretty much like a new access to an old pipe. | |
571 * Fix up pointers to match "old pipe" code | |
572 | |
573 IsAsOld tfr U,X ;Point Reg-X at pipe buffer | |
574 tfr Y,U ;Point Reg-U at driver static storage | |
575 ldy 10,S ;Recover PD pointer | |
576 stx PD.BUF,Y ;Set up buffer pointer in PD | |
577 bra OpnXit ; (go to common trailer code) | |
578 | |
579 * Pipe name found. Set up to access an old pipe. | |
580 * | |
581 * Reg-U points to driver static storage. | |
582 * Reg-X points to matching pipe buffer. | |
583 * | |
584 * We need to make this look like a DUP call, so | |
585 * there's some nasty code here to give back the | |
586 * PD allocated by IOMan and go get the "original" | |
587 * PD for this named pipe. | |
588 | |
589 OldPipe equ * | |
590 | |
591 *** *** | |
592 * WARNING -- This code emulates IOMan's I$Close and I$Dup * | |
593 *** *** | |
594 | |
595 * | |
596 * Processing to give back the new path descriptor and use | |
597 * the original PD that the pipe was opened with. | |
598 * | |
599 * Fake close of PD passed by IOMan | |
600 * Fake dup of named pipe's "master" PD | |
601 * Fix PD pointer saved on IOMAN's stack | |
602 * | |
603 * All of the subroutines preserve all regs, except as noted | |
604 * This section MUST preserve Reg-X and Reg-U. There must | |
605 * be exactly 14 bytes on the stack at this point. | |
606 | |
607 ldy 10,S ;Get IOMAN PD pointer (original Reg-Y) | |
608 | |
609 * Detach the path. | |
610 | |
611 pshs U | |
612 ldu PD.DEV,Y ; Get device pointer | |
613 os9 I$Detach ; Detach to compensate for IOMAN Attach | |
614 puls U | |
615 | |
616 * Decrement use count | |
617 | |
618 dec PD.CNT,Y ;Decrement use count | |
619 | |
620 * Give back unwanted PD | |
621 | |
622 *** This is the way I did it originally | |
623 pshs X | |
624 lda PD.PD,Y ;Get system path number | |
625 ldx <D.PthDBT ;Point at path table index | |
626 os9 F$Ret64 ; and give back descriptor | |
627 puls X | |
628 *** This is the way the OSK named pipe manager does it. | |
629 *** I had to translate, of course, but the translated | |
630 *** version doesn't work right. | |
631 * pshs U,X | |
632 * lda PD.PD,Y ;Get system path # | |
633 * ldx <D.PthDBT ;Point at path table index | |
634 * ldu <D.SysDis ;Point at system SVC dispatch table | |
635 * jsr [(F$Ret64*2),U] ;Do a RET64 | |
636 * puls X,U | |
637 | |
638 * Stack clean. | |
639 * Update IOMAN variables. | |
640 * Reg-Y = where IOMAN thinks the PD is. | |
641 | |
642 ifeq (CAUTION-CAREFUL) | |
643 cmpy (14+IOMAGIC),S ;Make sure the stack looks right (PD matches) | |
644 beq OKMagic | |
645 | |
646 * Stack is wrong; declare bad magic! | |
647 | |
648 comb | |
649 ldb #E$Bug | |
650 leas 14,S | |
651 rts | |
652 endc | |
653 | |
654 * Stack is right; go fix PD pointers | |
655 | |
656 OKMagic ldy PP.PD,X ;Get PD pointer of existing named pipe PD. | |
657 sty 10,S ;Point PD pointer at existing PD | |
658 sty (14+IOMAGIC),S ;Save new IOMAN PD pointer in IOMAN stack | |
659 inc PD.CNT,Y ;Increment use count | |
660 | |
661 * End of dangerous code | |
662 * This section MUST have preserved Reg-X and Reg-U | |
663 | |
664 * Exit code. | |
665 * | |
666 * Reg-U points to driver static storage. | |
667 * Reg-Y points to PD. | |
668 * Reg-X points to matching pipe buffer. | |
669 * | |
670 * Advance caller's path name pointer | |
671 | |
672 OpnXit equ * | |
673 | |
674 * Fix use count based on PD.Keep | |
675 | |
676 lda PD.CNT,Y | |
677 suba PD.Keep,Y | |
678 sta PD.CNT,Y ;Get rid of any artificial openings | |
679 clr PD.Keep,Y | |
680 | |
681 ifeq (PIPEDIR-YESDIR) | |
682 * Handle prefill of pipe directory buffer | |
683 | |
684 lda PD.Mod,Y ;Is this a DIR. open? | |
685 bita #DIR. | |
686 beq OpnXt2 | |
687 | |
688 lbsr FilDirP ;Send directory info to pipe | |
689 endc | |
690 | |
691 OpnXt2 ldu 12,S ;Point at caller's registers | |
692 ldd 4,S ;Get revised path name pointer | |
693 std R$X,U | |
694 | |
695 leas 14,S ;Clean the stack | |
696 | |
697 * Successful exit. Reg-X points to pipe buffer. | |
698 | |
699 clrb | |
700 rts | |
701 | |
702 page | |
703 * | |
704 * Compare pipe names. | |
705 * | |
706 * Can't use F$CmpNam here because the strings | |
707 * are in system space. | |
708 * | |
709 * Path names are pointed to by Reg-X and Reg-Y. | |
710 * Case is ignored. Returns NE if not equal, else | |
711 * EQ. | |
712 * | |
713 | |
714 Compare pshs Y,X,A ;Reg-A is temp. storage | |
715 | |
716 * Main comparison loop | |
717 | |
718 Cmp001 lda ,X+ | |
719 anda #%11011111 ;Cheap and fast TOUPPER | |
720 sta 0,S | |
721 | |
722 lda ,Y+ | |
723 anda #%11011111 ;Cheap and fast TOUPPER | |
724 bmi Cmp.Y ; (exit if we find end of Y-string) | |
725 | |
726 cmpa 0,S | |
727 beq Cmp001 | |
728 | |
729 * Names don't match. Return CC=NE | |
730 | |
731 puls A,X,Y,PC | |
732 | |
733 * End of "Y" string. "X" character either matches or | |
734 * it doesn't. Return CC accordingly. | |
735 | |
736 Cmp.Y cmpa 0,S | |
737 puls A,X,Y,PC | |
738 | |
739 * | |
740 * Convert element count in D to byte count in D. | |
741 * Return carry set if too big. | |
742 * | |
743 * Reg-Y = PD pointer | |
744 * Reg-D = Element count | |
745 * | |
746 | |
747 ECtoBC pshs D | |
748 lda PD.ESiz,Y ;Get size of each element | |
749 ldb 0,S ;Get MSB of element count | |
750 mul | |
751 pshs D | |
752 lda PD.ESiz,Y ;Get size of each element | |
753 ldb (2+1),S ;Get LSB of element count | |
754 mul | |
755 adda 1,S ;C-bit set if too big | |
756 tst ,S++ ;Z-bit clear if too big, C-bit OK | |
757 leas 2,S | |
758 bcs EB.err | |
759 bne EB.err | |
760 | |
761 * OK exit | |
762 andcc #^Carry | |
763 rts | |
764 | |
765 * Error exit | |
766 EB.err orcc #Carry | |
767 rts | |
768 | |
769 * Get next character of path name. | |
770 * Reg-Y set up as if just did a PRSNAM. | |
771 | |
772 GtNext ldx <D.Proc | |
773 ldb P$Task,X | |
774 tfr Y,X | |
775 os9 F$LDABX | |
776 rts | |
777 | |
778 page | |
779 * | |
780 * Error hook | |
781 * | |
782 MAKDIR equ * | |
783 CHGDIR equ * | |
784 UNKNOWN comb | |
785 ldb #E$UNKSVC | |
786 rts | |
787 | |
788 page | |
789 * | |
790 * Close a pipe | |
791 * | |
792 * If there are any other pipe users, leave the pipe | |
793 * around. Also, if the pipe is named and contains | |
794 * any data, leave the pipe around even if there are | |
795 * no remaining pipe users. | |
796 * | |
797 * PD.Keep will be non-zero if the pipe has been kept | |
798 * open artificially. | |
799 * | |
800 * This routine is called each time a path to the pipe | |
801 * is closed. | |
802 * | |
803 | |
804 CLOSE equ * | |
805 | |
806 * Account for extra use count if pipe artificially kept open. | |
807 * Then see if this is the last user of the pipe | |
808 | |
809 lda PD.Keep,Y ;Account for extra pipe images | |
810 nega | |
811 clr PD.Keep,Y | |
812 adda PD.CNT,Y | |
813 sta PD.CNT,Y ;Set correct PD.CNT value | |
814 bne READERS ; and branch if any users left | |
815 | |
816 * No open paths to this pipe. | |
817 * If it's named and not empty, leave it around anyway. | |
818 | |
819 tst PD.Name,Y ;Named pipe? | |
820 beq CLOSE2 | |
821 | |
822 ldd PD.BCnt,Y ;How many elements buffered on named pipe? | |
823 beq CLOSE2 | |
824 | |
825 * Leave this named pipe around for a while | |
826 | |
827 inc PD.CNT,Y ;Create an extra image | |
828 inc PD.Keep,Y ; and remember that we did it | |
829 bra CLOXIT | |
830 | |
831 * Delete the pipe. | |
832 * Y = PD pointer. | |
833 | |
834 CLOSE2 bsr ZapPipe | |
835 bra CloXit ;No error | |
836 | |
837 * Open paths left. What kind? | |
838 | |
839 READERS cmpa PD.RCT,Y ;Are all open paths readers? | |
840 bne WRITERS | |
841 | |
842 * All other open paths are readers. | |
843 * Send signal to next reader (let him read a bit) | |
844 | |
845 leax PD.Read,Y | |
846 bra SENDSIG | |
847 | |
848 * Not all readers. What kind? | |
849 | |
850 WRITERS cmpa PD.WCT,Y ;Are all open paths writers? | |
851 bne CloXit | |
852 | |
853 * All other open paths are writers. | |
854 * Send signal to next writer (let him write a bit) | |
855 | |
856 leax PD.Writ,Y | |
857 | |
858 * Send signal to next reader or writer | |
859 | |
860 SENDSIG lda PM.CPR,X ;Process ID to signal | |
861 beq CLOXIT | |
862 | |
863 ldb PM.SIG,X ;Signal code to send | |
864 beq CLOXIT | |
865 | |
866 * Committed to send signal: clear the flag and send it | |
867 | |
868 clr PM.SIG,X ;Force no pending signal | |
869 os9 F$SEND | |
870 | |
871 * Done with close | |
872 | |
873 CLOXIT clrb | |
874 rts | |
875 | |
876 page | |
877 * | |
878 * Delete a named pipe. | |
879 * | |
880 * Reg-Y = PD | |
881 * Reg-U = caller's registers | |
882 * Reg-X = path name | |
883 * | |
884 | |
885 Delete lda #Read. | |
886 sta PD.MOD,Y ;Need only READ permission | |
887 pshs U,Y,X,A ;***Match stack set up by IOMAN | |
888 lbsr Open ;Try to open the pipe | |
889 puls U,Y,X,A ;***Clean up special stack | |
890 bcs BadDel | |
891 | |
892 * Disconnect from pipe, but keep pointer. | |
893 * Then check to see if we're the only user. | |
894 * | |
895 * Note -- The call to OPEN updated PD.CNT | |
896 * and cleared PD.Keep. | |
897 | |
898 dec PD.CNT,Y ;Don't count ourselves | |
899 beq DoDel ;If count is zero, OK to delete | |
900 | |
901 * Pipe is in use. Return E$FNA | |
902 | |
903 FNAXIT comb | |
904 ldb #E$FNA | |
905 | |
906 * Exit w/ carry set and error code in B | |
907 | |
908 BadDel rts | |
909 | |
910 * Perform the delete. | |
911 | |
912 DoDel bsr ZapPipe | |
913 clrb | |
914 rts | |
915 | |
916 * | |
917 * Return all memory for the pipe buffer specified | |
918 * in the path descriptor, and remove it from the linked list. | |
919 * | |
920 * Reg-Y = PD pointer | |
921 * Pipe buffer pointer is at PD.BUF,Y | |
922 * | |
923 | |
924 ZapPipe ldu PD.DEV,Y ;Get device table pointer | |
925 ldu V$Stat,U ;Get static storage pointer | |
926 | |
927 ldx PD.BUF,Y ;Point to pipe's buffer | |
928 ldd PP.Next,X ;Save pointer to current and next in list | |
929 pshs D | |
930 ldd PP.Prev,X ;Save pointer to previous in list | |
931 pshs D | |
932 | |
933 * Reg-D has pointer to previous. If zero, we're zapping head of list. | |
934 * Z-bit is already set accordingly | |
935 | |
936 bne OldHead | |
937 | |
938 * New head of list. | |
939 * Reg-X still points to buffer to be deleted | |
940 | |
941 ldd 2,S ;Get pointer to next (may be $0000) | |
942 std V.List,U ; and set as new head | |
943 pshs X,D | |
944 ldx 0,S ;Point Reg-X at next, set CC | |
945 beq Zap9 | |
946 clr (PP.Prev+0),X ; and set no prev for next | |
947 clr (PP.Prev+1),X | |
948 Zap9 puls D,X ;Point back at pipe to delete | |
949 bra ZapIt | |
950 | |
951 * No new head of list. Just delete from linked list. | |
952 * We know there is a previous buffer. | |
953 * | |
954 * Reg-X points to buffer to be deleted. | |
955 * Reg-D points to previous buffer. | |
956 | |
957 OldHead ldu PP.Next,X ;Get U pointing at our next (may be $0000) | |
958 exg D,X ;Point X at our prev, D at us | |
959 stu PP.Next,X ;Save new next for out prev | |
960 beq Zap8 | |
961 stx PP.Prev,U ;Point our next's prev at our original prev | |
962 Zap8 exg D,X | |
963 | |
964 * All cleaned up. Give back the buffer | |
965 * Reg-X points to buffer, Reg-Y points to PD. | |
966 | |
967 ZapIt ldd PD.End,Y | |
968 pshs X | |
969 subd 0,S ;Get total bytes to Reg-D | |
970 puls U ;Point at buffer, clean stack | |
971 os9 F$SRtMem | |
972 | |
973 * Exit with whatever error F$SRtMem produces | |
974 | |
975 leas 4,S ;Clean stack | |
976 rts | |
977 | |
978 page | |
979 * | |
980 * Dummy hook | |
981 * | |
982 SEEK equ * | |
983 Dummy clrb | |
984 rts | |
985 | |
986 page | |
987 * | |
988 * GETSTT processing | |
989 * | |
990 * Supports the following codes: | |
991 * | |
992 * SS.Opt Option section | |
993 * SS.Ready # bytes in queue | |
994 * SS.Siz Size of queue | |
995 * SS.EOF Queue empty | |
996 * SS.FD Bogus file descriptor (WIZBANG==MSGS) | |
997 * SS.ScSiz Screen Size | |
998 * | |
999 * SS.Opt handled in IOMAN, etc. | |
1000 * SS.Ready code by Kent Meyers, modified by Chris Burke | |
1001 * SS.Siz, SS.EOF, SS.FD, SS.ScSiz by Chris Burke | |
1002 * | |
1003 | |
1004 GETSTT lda R$B,U Get User B Register ++ | |
1005 cmpa #SS.READY Test for Ready Call ++ | |
1006 bne NotSSRDY | |
1007 | |
1008 * Process SS.Rdy -- return # elements in queue | |
1009 * If more than 255, return 255. | |
1010 | |
1011 G.Rdy ldb #255 | |
1012 tst (PD.BCnt+0),Y | |
1013 bne G.Rdy0 ;Accomodate large queues (256 or more bytes) | |
1014 ldb (PD.BCnt+1),X ;Get element count LSB | |
1015 | |
1016 * Reg-B has LSB of element count, CC set based on value | |
1017 | |
1018 beq RDNRDY ;Not Ready if no characters | |
1019 | |
1020 G.Rdy0 stb R$B,U ;Return count in B | |
1021 | |
1022 SST.OK equ * | |
1023 SST.Ign equ * | |
1024 | |
1025 G.OK clrb No Error ++ | |
1026 tfr CC,A | |
1027 sta R$CC,U | |
1028 rts Return ++ | |
1029 | |
1030 * No characters for SS.Ready | |
1031 | |
1032 RDNRDY tst PD.Wrtn,Y Anybody writing to pipe? | |
1033 bne NOTEOF (not OK if so) | |
1034 | |
1035 * No writer | |
1036 | |
1037 ldb PD.CNT,Y Exactly one path open to pipe? | |
1038 decb | |
1039 bne NOTEOF (OK if no, e.g. nobody or > 1) | |
1040 | |
1041 * Internal error | |
1042 | |
1043 IntErr comb | |
1044 ldb #255 | |
1045 rts | |
1046 | |
1047 NOTEOF comb Set Error Flag ++ | |
1048 ldb #E$NOTRDY Get Error Code ++ | |
1049 rts Return ++ | |
1050 | |
1051 * Not SS.Ready. Check for SS.Siz | |
1052 | |
1053 NotSSRdy cmpa #SS.Size Test for Size call | |
1054 bne NotSSSiz | |
1055 | |
1056 * Process SS.Siz -- return size of queue in ELEMENTS. | |
1057 | |
1058 G.Siz ldd PD.QSiz,Y ;Get max. # of queue elements | |
1059 std R$U,U | |
1060 clr (R$X+0),U Set 16 MSB's to $0000 | |
1061 clr (R$X+1),U | |
1062 GOK001 bra G.OK | |
1063 | |
1064 * Not SS.Siz. Check for SS.EOF | |
1065 | |
1066 NotSSSiz cmpa #SS.EOF | |
1067 bne NotSSEOF | |
1068 | |
1069 * Process SS.EOF | |
1070 * Handle like SS.Rdy, but preserve Reg-B | |
1071 | |
1072 G.EOF bsr G.Siz | |
1073 ldb #0 ;NOT clrb -- preserve carry | |
1074 stb R$B,U | |
1075 bcc G.OK ;No error if ready | |
1076 | |
1077 ldb #E$EOF ;Carry is already set | |
1078 rts | |
1079 | |
1080 * Not SS.EOF. Check for SS.FD | |
1081 | |
1082 ifeq (PIPEDIR-YESDIR) | |
1083 NotSSEOF cmpa #SS.FD | |
1084 bne NotSSFD | |
1085 | |
1086 * Process SS.FD | |
1087 | |
1088 lbsr DoSSFD | |
1089 bra G.OK ;Successful always | |
1090 else | |
1091 NotSSEOF equ * | |
1092 endc | |
1093 | |
1094 * Not SS.FD. Check for SS.ScSiz | |
1095 | |
1096 NotSSFD cmpa #SS.ScSiz ;Force UNKNOWN here | |
1097 lbeq UnKnown | |
1098 | |
1099 NotSCSZ equ * | |
1100 | |
1101 NotSSAT equ * | |
1102 | |
1103 * Process unknown GETSTT | |
1104 | |
1105 * lbra UNKNOWN | |
1106 bra G.OK | |
1107 * bra NotEOF | |
1108 | |
1109 page | |
1110 * | |
1111 * SETSTT processing | |
1112 * | |
1113 * Supports the following codes: | |
1114 * | |
1115 * SS.Opt Option section | |
1116 * SS.Siz No effect unless size=0; then clears pipe buffer | |
1117 * SS.FD No effect | |
1118 * SS.SSig Set signal on data available | |
1119 * SS.Relea Release signal | |
1120 * | |
1121 * SS.Opt handled in IOMAN, etc. | |
1122 * SS.Siz, SS.SSig, SS.Relea by Chris Burke, modified | |
1123 * from OSK. | |
1124 * | |
1125 | |
1126 SetStt lda R$B,U Get User B Register ++ | |
1127 cmpa #SS.Opt | |
1128 beq SST.Ign ; (ignore) | |
1129 cmpa #SS.FD | |
1130 beq SST.Ign | |
1131 | |
1132 * Check for SS.SIZ | |
1133 | |
1134 cmpa #SS.Size | |
1135 bne NoS.Siz | |
1136 | |
1137 ldd R$U,U ;Get caller's size | |
1138 bne SST.Ign | |
1139 | |
1140 * Clear the pipe | |
1141 | |
1142 ldx PD.Buf,Y | |
1143 leau PP.Data,X | |
1144 stu PD.NxtI,Y | |
1145 stu PD.NxtO,Y | |
1146 clr (PD.BCnt+0),Y | |
1147 clr (PD.BCnt+1),Y | |
1148 clr PD.RFlg,Y | |
1149 clr PD.Wrtn,Y | |
1150 | |
1151 QST.OK bra SST.OK | |
1152 | |
1153 * Check for SS.SSig | |
1154 | |
1155 NoS.Siz cmpa #SS.SSig | |
1156 bne NoS.Sig | |
1157 | |
1158 leax PD.Read,Y ;Point at read packet | |
1159 tst PM.Cpr,X ;Error if already somebody waiting | |
1160 bne NOTEOF | |
1161 | |
1162 * Set signal trap | |
1163 | |
1164 lda PD.CPR,Y ;Set process ID | |
1165 sta PM.CPR,X | |
1166 lda (R$X+1),U ;Get signal code | |
1167 sta PM.Sig,X | |
1168 tst PD.BCnt,Y ;Immediate signal if | |
1169 lbne SendSig | |
1170 | |
1171 bra QST.OK | |
1172 | |
1173 * Check for release of signal | |
1174 | |
1175 NoS.Sig cmpa #SS.Relea | |
1176 bne NoS.Rel | |
1177 | |
1178 leax PD.Read,Y ;Point at read packet | |
1179 lda PM.CPR,X | |
1180 cmpa PD.CPR,Y ;Our process set it? | |
1181 bne QST.OK | |
1182 | |
1183 * Release signal trap | |
1184 | |
1185 clrb | |
1186 lbra Switch | |
1187 | |
1188 * Not SS.Relea. Check for SS.Attr | |
1189 | |
1190 NoS.Rel cmpa #SS.Attr | |
1191 bne NoS.Atr | |
1192 | |
1193 * Change attributes if allowed | |
1194 | |
1195 ldx <D.Proc | |
1196 lda P$ID,X ;Are we superuser? | |
1197 beq SAT.OK | |
1198 tst PD.Own,Y ;Is creator still attached? | |
1199 bne SAT.XX | |
1200 | |
1201 sta PD.Own,Y ;Inherit pipe if owner abandoned it | |
1202 | |
1203 SAT.XX cmpa PD.Own,Y | |
1204 lbne FNAXit ;If can't match PID, E$FNA error | |
1205 | |
1206 * Change attributes. | |
1207 * Reg-U points at caller's registers | |
1208 | |
1209 SAT.OK lda R$A,U | |
1210 ora #(READ.+WRITE.) ;We insist . . . | |
1211 sta PD.MOD,Y | |
1212 bra QST.OK | |
1213 | |
1214 * Unknown SETSTT | |
1215 | |
1216 NoS.Atr lbra Unknown | |
1217 | |
1218 page | |
1219 * | |
1220 * Read CR-terminated line or element count from | |
1221 * pipe with no editing. Note that this call is | |
1222 * not well defined for element sizes other than | |
1223 * 1 byte. | |
1224 * | |
1225 | |
1226 READLN ldb PD.ESiz,Y | |
1227 decb | |
1228 bne RddEOF ;EOF error if more than 1 byte per element | |
1229 | |
1230 ldb #CR | |
1231 stb PD.REOR,Y | |
1232 bra READ001 | |
1233 | |
1234 * | |
1235 * Read element count from pipe with no editing. | |
1236 * | |
1237 * Note that if there are fewer elements in the pipe | |
1238 * than the user wants to read, and there are no writers | |
1239 * for the pipe, we return all elements followed by E$EOF. | |
1240 * | |
1241 | |
1242 READ clr PD.REOR,Y | |
1243 | |
1244 * Generic read. PD.REOR = terminator if non-null | |
1245 | |
1246 READ001 leax PD.Read,Y ;Get PID of reader (us) | |
1247 lbsr GETFREE | |
1248 bcs RddRTS | |
1249 | |
1250 ldd R$Y,U ;Desired element count | |
1251 beq RddXit | |
1252 | |
1253 * Set up for outer loop -- push zero element count | |
1254 * and space for buffer pointers on stack. | |
1255 | |
1256 clra | |
1257 clrb | |
1258 pshs D ;Initial count of elements read | |
1259 leas -4,S | |
1260 ldx R$X,U ;Initial buffer start address | |
1261 bra RddNext | |
1262 | |
1263 * Enter here to block on read. If there are no writers, | |
1264 * return E$EOF. | |
1265 | |
1266 CantRdd pshs X ;Save buffer pointer | |
1267 | |
1268 leax PD.Read,Y | |
1269 lbsr SigSlp | |
1270 lbcs RddDone | |
1271 | |
1272 * Inner loop to read bytes. | |
1273 * Here for initial attempt to read, | |
1274 * or to retry after blocking | |
1275 | |
1276 READOK ldx <D.PROC ;Point to our task descriptor | |
1277 ldb P$TASK,X ++LII | |
1278 puls X ++LII Recover current buffer pointer | |
1279 | |
1280 * Inner read loop. Read one element. | |
1281 * Note that we could use F$Move for elements larger | |
1282 * than 1 byte, because queue size is always an even | |
1283 * multiple of element size. | |
1284 | |
1285 RddMore lbsr DOREAD ;Get byte to A, or CS | |
1286 bcs CantRdd | |
1287 | |
1288 os9 F$STABX ;Put byte in caller's buffer | |
1289 leax 1,X | |
1290 tst PD.REOR,Y ;Is there an EOR character? | |
1291 beq NotRdLn | |
1292 | |
1293 cmpa PD.REOR,Y ;Did we match it? | |
1294 beq RddEOL | |
1295 | |
1296 NotRdLn cmpx 0,S ;Compare current addr. to end addr | |
1297 blo RddMore ; and loop until done | |
1298 | |
1299 * Done with element. Check for next. | |
1300 | |
1301 pshs X ;Save buffer pointer | |
1302 | |
1303 bsr CntDn ;Update queue count, etc | |
1304 cmpd R$Y,U ;Got all elements? | |
1305 bhs RddTail | |
1306 | |
1307 * Outer loop -- read one element at a time. | |
1308 * | |
1309 * X = next data pointer | |
1310 * Y = PD pointer | |
1311 | |
1312 RddNext stx 0,S ;Set new start address | |
1313 ldb PD.ESiz,Y ;Size of one element | |
1314 clra | |
1315 addd 0,S ;Compute end address of current element bfr | |
1316 std 2,S | |
1317 bra READOK ;Go to element reading loop | |
1318 | |
1319 * Read an EOL. Advance element count | |
1320 | |
1321 RddEOL pshs X ;Save buffer pointer | |
1322 bsr CntDn | |
1323 | |
1324 * Read everything, or aborting | |
1325 | |
1326 RddDone ldd 4,S ;Get element count | |
1327 | |
1328 * Tail end of read | |
1329 | |
1330 RddTail std R$Y,U | |
1331 leas 6,S ;Clean stack | |
1332 bne RddSome ;Success if read more than 0 elements | |
1333 | |
1334 * EOF error if no bytes read | |
1335 | |
1336 RddEOF comb | |
1337 ldb #E$EOF | |
1338 bra RddXit | |
1339 | |
1340 * Successful exit | |
1341 | |
1342 RddSome clrb | |
1343 | |
1344 RddXit leax PD.Read,Y | |
1345 lbra SWITCH | |
1346 | |
1347 * Decrement queued count, inc read count | |
1348 | |
1349 CntDn ldd #-1 | |
1350 bra CUpDn | |
1351 | |
1352 * Increment queued count, inc written count | |
1353 | |
1354 CntUp ldd #1 | |
1355 | |
1356 CUpDn addd PD.BCnt,Y ;Modify count of elements queued | |
1357 std PD.BCnt,Y | |
1358 | |
1359 * Bump I/O count | |
1360 | |
1361 IOCnt ldd (2+4),S ;Bump count of elements read/written | |
1362 addd #1 | |
1363 std (2+4),S | |
1364 RDDRTS rts | |
1365 | |
1366 page | |
1367 * | |
1368 * Write CR-terminated line or element count to | |
1369 * pipe with no editing | |
1370 * | |
1371 | |
1372 WRITELN ldb PD.ESiz,Y | |
1373 decb | |
1374 bne RddEOF ;EOF error if more than 1 byte per element | |
1375 | |
1376 ldb #CR | |
1377 stb PD.WEOR,Y | |
1378 bra Wrt001 | |
1379 | |
1380 * | |
1381 * Write byte count to pipe with no editing. | |
1382 * | |
1383 | |
1384 WRITE clr PD.WEOR,Y | |
1385 | |
1386 * Generic entry point | |
1387 | |
1388 Wrt001 leax PD.Writ,Y | |
1389 lbsr GETFREE ;Check I/O queue | |
1390 bcs WrtXit | |
1391 | |
1392 ldd R$Y,U ;Element count | |
1393 beq WrtXit | |
1394 | |
1395 * Set up for outer loop -- push zero element count | |
1396 * and space for buffer pointers on stack. | |
1397 | |
1398 clra | |
1399 clrb | |
1400 pshs D ;Initial count of elements read | |
1401 leas -4,S | |
1402 ldx R$X,U ;Initial buffer start address | |
1403 bra WrtNext | |
1404 | |
1405 * Enter here to block on write | |
1406 | |
1407 CantWrt pshs X | |
1408 | |
1409 leax PD.Writ,Y | |
1410 lbsr SigSlp | |
1411 bcs WrtErr | |
1412 | |
1413 * Begin (or resume) write | |
1414 | |
1415 WRITOK ldx <D.PROC ++LII | |
1416 ldb P$TASK,X ;Get our DAT image # | |
1417 puls X ++LII | |
1418 | |
1419 * Main write loop | |
1420 | |
1421 WrtMore os9 F$LDABX ;Get a byte from caller's buffer | |
1422 lbsr DOWRITE | |
1423 bcs CantWrt | |
1424 | |
1425 leax 1,X | |
1426 tst PD.WEOR,Y ;EOL character defined? | |
1427 beq NotWrLn | |
1428 | |
1429 cmpa PD.WEOR,Y | |
1430 beq WrtEOL | |
1431 | |
1432 * See if at end of buffer | |
1433 | |
1434 NotWrLn cmpx 0,S | |
1435 blo WrtMore | |
1436 | |
1437 * Done with element. Check for next. | |
1438 | |
1439 pshs X ;Save buffer pointer | |
1440 | |
1441 bsr CntUp | |
1442 cmpd R$Y,U ;Put all elements? | |
1443 bhs WrtTail | |
1444 | |
1445 * Outer loop -- write one element at a time. | |
1446 | |
1447 WrtNext stx 0,S ;Set new start address | |
1448 ldb PD.ESiz,Y ;Size of one element | |
1449 clra | |
1450 addd 0,S ;Compute end address of current element bfr | |
1451 std 2,S | |
1452 bra WRITOK ;Go to element reading loop | |
1453 | |
1454 * Wrote an EOL. Advance element count | |
1455 | |
1456 WrtEOL pshs X ;Save buffer pointer | |
1457 bsr CntUp | |
1458 | |
1459 * Wrote everything, or aborting | |
1460 | |
1461 WrtDone ldd 4,S ;Get element count | |
1462 | |
1463 * Tail end of write | |
1464 | |
1465 WrtTail std R$Y,U | |
1466 leas 6,S ;Clean stack | |
1467 | |
1468 * Successful exit | |
1469 | |
1470 WrtSome clrb | |
1471 | |
1472 WrtXit leax PD.Writ,Y | |
1473 bra SWITCH | |
1474 | |
1475 * Error exit | |
1476 | |
1477 WrtErr pshs B | |
1478 ldd (4+1),S | |
1479 std R$Y,U | |
1480 puls B | |
1481 | |
1482 leas 6,S | |
1483 bra WrtXit | |
1484 | |
1485 page | |
1486 * | |
1487 * I/O queue manipulation routines | |
1488 * | |
1489 | |
1490 GETFREE lda PM.CPR,X ;Is any process using this resource? | |
1491 beq SETPMCPR ; (branch if not) | |
1492 | |
1493 cmpa PD.CPR,Y ;Does caller control this resource? | |
1494 beq OURDEVIC ; (branch if so) | |
1495 | |
1496 inc PM.CNT,X ;Bump # of active r/w images | |
1497 ldb PM.CNT,X | |
1498 cmpb PD.CNT,Y ;See if equal to # of open images | |
1499 bne SETQUEUE ; (if not, run everybody else to free it) | |
1500 | |
1501 lbsr SENDSIG ;Yes -- wake up next process | |
1502 | |
1503 * Process number in Reg-A | |
1504 * Put the process into the I/O queue and | |
1505 * sleep until a signal wakes us up | |
1506 | |
1507 SETQUEUE os9 F$IOQU | |
1508 dec PM.CNT,X ;Caller is asleep, so 1 less active | |
1509 pshs X | |
1510 ldx <D.PROC | |
1511 ldb P$SIGNAL,X ;Get caller's signal | |
1512 puls X | |
1513 beq GETFREE ;Loop until there's a signal | |
1514 | |
1515 coma ;Error if caller is waiting | |
1516 rts | |
1517 | |
1518 * Nobody using the resource. Grab it. | |
1519 | |
1520 SETPMCPR ldb PD.CPR,Y | |
1521 stb PM.CPR,X ;Make caller "owner" | |
1522 | |
1523 * Exit -- caller owns the pipe | |
1524 | |
1525 OURDEVIC clrb | |
1526 rts | |
1527 | |
1528 * | |
1529 * Set a wakeup signal for the calling process | |
1530 * | |
1531 | |
1532 SigSlp ldb PM.CNT,X ;Active image count | |
1533 incb | |
1534 cmpb PD.CNT,Y ;Everybody active? | |
1535 bne SgSlp01 ; (if not, try sending signals) | |
1536 | |
1537 * Nobody on the other end to signal. | |
1538 * Error if anonymous, else hang out a bit. | |
1539 | |
1540 tst PD.Name,Y ;If anonymous pipe & nobody left, error | |
1541 beq WRITEROR | |
1542 | |
1543 * Named pipe and nobody to signal. Not an error if data in pipe. | |
1544 | |
1545 tst PD.BCnt,Y ;Number of items in pipe | |
1546 beq WRITEROR | |
1547 | |
1548 * Send signal to other end of pipe (may not be one, though) | |
1549 | |
1550 SgSlp01 stb PM.CNT,X | |
1551 ldb #S$WAKE | |
1552 stb PM.SIG,X ;Force caller's signal to "wakeup" | |
1553 clr PD.CPR,Y | |
1554 pshs X | |
1555 tfr X,D ;Switch from reader to writer or vis-a-vis | |
1556 eorb #4 | |
1557 tfr D,X | |
1558 lbsr SENDSIG ;Send signal to opposite end of pipe | |
1559 ldx #0 | |
1560 os9 F$SLEEP ;Caller sleeps until signaled | |
1561 ldx <D.PROC | |
1562 ldb P$SIGNAL,X | |
1563 puls X | |
1564 dec PM.CNT,X ;Caller is asleep, so 1 less active | |
1565 tstb | |
1566 bne GOTSIGNL ;Error if opposite end set no signal | |
1567 | |
1568 clrb | |
1569 rts | |
1570 | |
1571 * WRITE ERROR hook | |
1572 | |
1573 WRITEROR ldb #E$WRITE | |
1574 | |
1575 * Generic error hook | |
1576 | |
1577 GOTSIGNL coma | |
1578 rts | |
1579 | |
1580 * | |
1581 * Release this end of the pipe, and | |
1582 * send a signal to the other end. | |
1583 * | |
1584 * Enter pointing to variables for | |
1585 * this end; exit pointing to variables | |
1586 * for opposite end. | |
1587 * | |
1588 | |
1589 SWITCH pshs CC,B,U | |
1590 clr PM.CPR,X ;No process controlling current end | |
1591 tfr X,D | |
1592 eorb #4 ;Switch to other end (MAGIC) | |
1593 tfr D,X | |
1594 lbsr SENDSIG ;Awaken other end | |
1595 puls CC,B,U,PC | |
1596 | |
1597 * | |
1598 * Write one byte to queue described in path | |
1599 * descriptor. Return CS if queue full. | |
1600 * Doesn't update count of ELEMENTS queued. | |
1601 * | |
1602 | |
1603 DOWRITE pshs B,X | |
1604 ldx PD.NxtI,Y | |
1605 ldb PD.RFlg,Y | |
1606 beq SETREADY ;(say data available) | |
1607 | |
1608 cmpx PD.NxtO,Y | |
1609 bne STORDATA ;(branch if queue not full) | |
1610 | |
1611 * Error -- queue is full | |
1612 | |
1613 comb | |
1614 puls B,X,PC | |
1615 | |
1616 * Mark data available in queue | |
1617 | |
1618 SETREADY ldb #1 | |
1619 stb PD.RFlg,Y | |
1620 | |
1621 * Put data in Reg-A into queue, and advance | |
1622 * pointer to next in w/ wrap | |
1623 | |
1624 STORDATA sta ,X+ | |
1625 cmpx PD.End,Y | |
1626 blo WTNOWRAP | |
1627 | |
1628 ldx PD.BUF,Y | |
1629 leax PP.Data,X | |
1630 | |
1631 WTNOWRAP stx PD.NxtI,Y | |
1632 | |
1633 * Don't step Character Input Counter. | |
1634 | |
1635 clr PD.Wrtn,Y | |
1636 puls B,X,PC | |
1637 | |
1638 * | |
1639 * Read one byte from queue described in path | |
1640 * descriptor. Return CS if none available. | |
1641 * Doesn't update count of ELEMENTS queued. | |
1642 * | |
1643 | |
1644 DOREAD lda PD.RFlg,Y ;Any data? | |
1645 bne DATAREDY | |
1646 | |
1647 * No data -- return CS | |
1648 | |
1649 comb | |
1650 rts | |
1651 | |
1652 * Get data from queue | |
1653 | |
1654 DATAREDY pshs X | |
1655 ldx PD.NxtO,Y ;Get next out pointer | |
1656 lda ,X+ | |
1657 cmpx PD.End,Y | |
1658 blo RDNOWRAP | |
1659 | |
1660 ldx PD.BUF,Y | |
1661 leax PP.Data,X | |
1662 | |
1663 * Save updated next out pointer | |
1664 | |
1665 RDNOWRAP stx PD.NxtO,Y | |
1666 cmpx PD.NxtI,Y | |
1667 bne NOTEMPTY | |
1668 | |
1669 clr PD.RFlg,Y ;Mark queue empty | |
1670 | |
1671 * Don't decrement Character Input Counter. | |
1672 | |
1673 NOTEMPTY equ * | |
1674 | |
1675 * Exit with character in Reg-A | |
1676 | |
1677 andcc #^Carry ;Clear carry | |
1678 puls X,PC | |
1679 | |
1680 page | |
1681 * | |
1682 * Utility placed here to not make assembly listing obsolete. | |
1683 * | |
1684 | |
1685 MovSet os9 F$Move ;Do inter-process block move | |
1686 | |
1687 * Force set MSB at end of name | |
1688 | |
1689 tfr Y,D ;Byte count to D | |
1690 decb | |
1691 lda B,U ;Get last byte of name | |
1692 ora #%10000000 | |
1693 sta B,U | |
1694 | |
1695 rts | |
1696 | |
1697 ifeq (PIPEDIR-YESDIR) | |
1698 | |
1699 * | |
1700 * Find out how many pipes there are for the | |
1701 * current device, and set up device descriptor | |
1702 * so that pipe buffer will hold 32 bytes of | |
1703 * data for each. | |
1704 * | |
1705 * Reg-Y = PD pointer | |
1706 * | |
1707 * Exit with size set up in PD. | |
1708 * CC=EQ if no pipes. | |
1709 * | |
1710 | |
1711 SizDirP pshs X,D | |
1712 | |
1713 clrb ;Clear count of pipes | |
1714 ldx PD.Dev,Y | |
1715 ldx V$Stat,X ;Point at static storage | |
1716 ldx V.List,X ;Get head of linked list | |
1717 beq GotCnt | |
1718 | |
1719 * There are some pipes. Count them. | |
1720 | |
1721 PCount incb | |
1722 ldx PP.Next,X ;Track down linked list | |
1723 bne PCount | |
1724 | |
1725 * Now Reg-B = pipe count. Need 32 bytes per pipe. | |
1726 | |
1727 GotCnt incb ;Add one for us! | |
1728 lda #32 | |
1729 mul | |
1730 std PD.QSiz,Y ;Set element count for this pipe | |
1731 lda #1 | |
1732 sta PD.ESiz,Y ;Set element size to 1 byte | |
1733 | |
1734 puls D,X,PC | |
1735 | |
1736 * | |
1737 * Fill pipe buffer with directory data. | |
1738 * | |
1739 * The data is organized like an RBF directory: | |
1740 * | |
1741 * Offset Data | |
1742 * -------- -------------------------------- | |
1743 * $00-$1C Pipe name | |
1744 * $1D DAT task number of pipe buffer | |
1745 * $1E-$1F Address of pipe buffer in task | |
1746 * | |
1747 * | |
1748 FilDirP pshs U,X,D | |
1749 | |
1750 ldx PD.Dev,Y | |
1751 ldx V$Stat,X ;Point at static storage | |
1752 ldx V.List,X ;Get head of linked list | |
1753 beq GotFil | |
1754 | |
1755 * Write data for pipe buffer @X to pipe with PD @Y | |
1756 | |
1757 FD000 ldu PP.PD,X ;Point at PD for pipe to be dumped | |
1758 leau PD.Name,u | |
1759 ldb #NameMax | |
1760 | |
1761 FD001 lda ,u+ ;Write pipe name | |
1762 bsr QWrite | |
1763 decb | |
1764 bne FD001 | |
1765 | |
1766 ldu <D.SysPrc ;Get system DAT image number | |
1767 lda P$Task,u | |
1768 bsr QWrite | |
1769 | |
1770 pshs X ;Get pipe buffer pointer | |
1771 lda ,S+ | |
1772 bsr QWrite | |
1773 lda ,S+ | |
1774 bsr QWrite | |
1775 | |
1776 * Advance to next pipe buffer | |
1777 | |
1778 ldx PP.Next,X | |
1779 bne FD000 | |
1780 | |
1781 * All done. Restore regs & exit | |
1782 | |
1783 GotFil puls D,X,U,PC | |
1784 | |
1785 * Byte saver | |
1786 | |
1787 QWrite lbra DoWrite | |
1788 | |
1789 * | |
1790 * Immortal entry point | |
1791 * | |
1792 Immort coma | |
1793 sbcb #38 | |
1794 lsrb | |
1795 fcb $42 ;SBCB op-code | |
1796 | |
1797 * Fall through to SS.FD processing | |
1798 | |
1799 * | |
1800 * Routine to process SS.FD call on an open pipe. | |
1801 * Creates a pseudo-FD in the user's buffer (@R$X). | |
1802 * Desired byte count in R$Y. | |
1803 * | |
1804 * The pseudo-file descriptor sector includes the following: | |
1805 * | |
1806 * Offset Description | |
1807 * -------- -------------------------------------- | |
1808 * $00 Attributes | |
1809 * $01-$02 Owner's *PROCESS* ID | |
1810 * $03-$07 Zeros (date of last access) | |
1811 * $08 Use count | |
1812 * $09-$0C Number of items queued | |
1813 * $0D-$0F Zeros (creation date) | |
1814 * $10-$FF Zeros (segment list -- at least 5 zeros needed) | |
1815 * | |
1816 | |
1817 DoSSFD pshs D,X,Y,U | |
1818 | |
1819 ldb #(16+5) ;Clear data on stack | |
1820 SSFD01 clr ,-S | |
1821 decb | |
1822 bne SSFD01 | |
1823 | |
1824 * Set attributes | |
1825 lda PD.Mod,Y | |
1826 sta FD.ATT,S | |
1827 | |
1828 * Set owner's process ID | |
1829 lda PD.Own,Y | |
1830 sta (FD.OWN+1),S | |
1831 | |
1832 * Set use count | |
1833 lda PD.CNT,Y | |
1834 sta FD.LNK,S | |
1835 | |
1836 * Set queue count | |
1837 | |
1838 ldd PD.BCNT,Y | |
1839 std (FD.SIZ+2),S | |
1840 | |
1841 * Now copy the data into the caller's buffer | |
1842 | |
1843 ldx <D.SysPrc ;Pointer to our PD | |
1844 lda P$Task,X ; get system's DAT image # (source) | |
1845 ldx <D.Proc ;Pointer to caller's PD | |
1846 ldb P$Task,X ; get caller's DAT image # (dest) | |
1847 ldy R$Y,U ;Byte count | |
1848 leax 0,S ;Source address | |
1849 ldu R$X,U ;Destination address | |
1850 os9 F$Move ;Do the move | |
1851 | |
1852 * All done. | |
1853 | |
1854 leas (16+5),S | |
1855 puls U,X,Y,D,PC | |
1856 | |
1857 endc | |
1858 | |
1859 emod | |
1860 | |
1861 MODSIZE equ * | |
1862 | |
1863 end | |
1864 |