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