fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/drivers/pri/pri.c *
7 * Created: 2012-01-31 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2012-2025 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26
27#include "pri.h"
28
29
30/*****************************************************************************
31 * Clear all bits in the range i1 < i <= i2 in buf
32 *****************************************************************************/
33static
34void pri_clear_bits (unsigned char *buf, unsigned long i1, unsigned long i2)
35{
36 unsigned char m1, m2;
37
38 if (i2 < i1) {
39 return;
40 }
41
42 m1 = ~(0xff >> (i1 & 7));
43 m2 = ~(0xff << (~i2 & 7));
44
45 i1 >>= 3;
46 i2 >>= 3;
47
48 if (i1 == i2) {
49 buf[i1] &= m1 | m2;
50 }
51 else {
52 buf[i1++] &= m1;
53
54 while (i1 < i2) {
55 buf[i1++] = 0;
56 }
57
58 buf[i2] &= m2;
59 }
60}
61
62pri_evt_t *pri_evt_new (unsigned long type, unsigned long pos, unsigned long val)
63{
64 pri_evt_t *evt;
65
66 if ((evt = malloc (sizeof (pri_evt_t))) == NULL) {
67 return (NULL);
68 }
69
70 evt->next = NULL;
71 evt->type = type;
72 evt->pos = pos;
73 evt->val = val;
74
75 return (evt);
76}
77
78void pri_evt_del (pri_evt_t *evt)
79{
80 free (evt);
81}
82
83/*
84 * Get the next event of type <type> after this one.
85 */
86pri_evt_t *pri_evt_next (pri_evt_t *evt, unsigned long type)
87{
88 if (evt != NULL) {
89 evt = evt->next;
90 }
91
92 while (evt != NULL) {
93 if ((type == PRI_EVENT_ALL) || (evt->type == type)) {
94 return (evt);
95 }
96
97 evt = evt->next;
98 }
99
100 return (NULL);
101}
102
103/*
104 * Convert the clock rate multiplication factor in an event of
105 * type PRI_EVENT_CLOCK to a real clock rate.
106 */
107unsigned long pri_evt_get_clock (pri_evt_t *evt, unsigned long base)
108{
109 unsigned long clk;
110
111 if ((evt == NULL) || (evt->type != PRI_EVENT_CLOCK)) {
112 return (base);
113 }
114
115 if (evt->val == 0) {
116 clk = base;
117 }
118 else {
119 clk = ((unsigned long long) evt->val * base + 32767) / 65536;
120 }
121
122 return (clk);
123}
124
125/*****************************************************************************
126 * Create a new track
127 *
128 * @param size The track size in bits
129 * @param clock The bit rate in Herz
130 *
131 * @return The new track or NULL on error
132 *****************************************************************************/
133pri_trk_t *pri_trk_new (unsigned long size, unsigned long clock)
134{
135 pri_trk_t *trk;
136
137 trk = malloc (sizeof (pri_trk_t));
138
139 if (trk == NULL) {
140 return (NULL);
141 }
142
143 trk->clock = clock;
144 trk->size = size;
145 trk->data = NULL;
146
147 if (size > 0) {
148 trk->data = malloc ((size + 7) / 8);
149
150 if (trk->data == NULL) {
151 free (trk);
152 return (NULL);
153 }
154 }
155
156 trk->evt = NULL;
157
158 trk->idx = 0;
159 trk->cur_evt = NULL;
160 trk->wrap = 0;
161
162 return (trk);
163}
164
165/*****************************************************************************
166 * Delete a track
167 *****************************************************************************/
168void pri_trk_del (pri_trk_t *trk)
169{
170 pri_evt_t *tmp;
171
172 if (trk != NULL) {
173 while (trk->evt != NULL) {
174 tmp = trk->evt;
175 trk->evt = tmp->next;
176 free (tmp);
177 }
178
179 free (trk->data);
180 free (trk);
181 }
182}
183
184/*****************************************************************************
185 * Create an exact copy of a track
186 *****************************************************************************/
187pri_trk_t *pri_trk_clone (const pri_trk_t *trk)
188{
189 pri_trk_t *ret;
190 pri_evt_t *evt;
191
192 ret = pri_trk_new (trk->size, trk->clock);
193
194 if (ret == NULL) {
195 return (NULL);
196 }
197
198 if (trk->size > 0) {
199 memcpy (ret->data, trk->data, (trk->size + 7) / 8);
200 }
201
202 ret->idx = trk->idx;
203 ret->cur_evt = NULL;
204 ret->wrap = trk->wrap;
205
206 evt = trk->evt;
207
208 while (evt != NULL) {
209 if (pri_trk_evt_add (ret, evt->type, evt->pos, evt->val) == NULL) {
210 pri_trk_del (ret);
211 return (NULL);
212 }
213
214 evt = evt->next;
215 }
216
217 return (ret);
218}
219
220void pri_trk_evt_ins (pri_trk_t *trk, pri_evt_t *evt)
221{
222 pri_evt_t *tmp;
223
224 evt->next = NULL;
225
226 if (trk->evt == NULL) {
227 trk->evt = evt;
228 }
229 else if (evt->pos < trk->evt->pos) {
230 evt->next = trk->evt;
231 trk->evt = evt;
232 }
233 else {
234 tmp = trk->evt;
235
236 while ((tmp->next != NULL) && (evt->pos >= tmp->next->pos)) {
237 tmp = tmp->next;
238 }
239
240 evt->next = tmp->next;
241 tmp->next = evt;
242 }
243}
244
245int pri_trk_evt_rmv (pri_trk_t *trk, const pri_evt_t *evt)
246{
247 pri_evt_t *tmp;
248
249 if (trk->evt == NULL) {
250 return (1);
251 }
252
253 if (trk->evt == evt) {
254 trk->evt = trk->evt->next;
255 return (0);
256 }
257
258 tmp = trk->evt;
259
260 while ((tmp->next != NULL) && (tmp->next != evt)) {
261 tmp = tmp->next;
262 }
263
264 if (tmp->next == evt) {
265 tmp->next = tmp->next->next;
266 return (0);
267 }
268
269 return (1);
270}
271
272pri_evt_t *pri_trk_evt_add (pri_trk_t *trk, unsigned long type, unsigned long pos, unsigned long val)
273{
274 pri_evt_t *evt;
275
276 if ((evt = pri_evt_new (type, pos, val)) == NULL) {
277 return (NULL);
278 }
279
280 pri_trk_evt_ins (trk, evt);
281
282 return (evt);
283}
284
285/*
286 * Get the first event of type <type>, after skipping idx events of the same
287 * type.
288 */
289pri_evt_t *pri_trk_evt_get_idx (pri_trk_t *trk, unsigned long type, unsigned long idx)
290{
291 pri_evt_t *evt;
292
293 evt = trk->evt;
294
295 while (evt != NULL) {
296 if ((type == PRI_EVENT_ALL) || (evt->type == type)) {
297 if (idx == 0) {
298 return (evt);
299 }
300
301 idx -= 1;
302 }
303
304 evt = evt->next;
305 }
306
307 return (NULL);
308}
309
310/*
311 * Get the first event of type <type> at <pos>.
312 */
313pri_evt_t *pri_trk_evt_get_pos (pri_trk_t *trk, unsigned long type, unsigned long pos)
314{
315 pri_evt_t *evt;
316
317 evt = trk->evt;
318
319 while (evt != NULL) {
320 if ((type == PRI_EVENT_ALL) || (evt->type == type)) {
321 if (evt->pos == pos) {
322 return (evt);
323 }
324
325 if (evt->pos > pos) {
326 return (NULL);
327 }
328 }
329
330 evt = evt->next;
331 }
332
333 return (NULL);
334}
335
336/*
337 * Get the first event of type <type> at or after <pos>.
338 */
339pri_evt_t *pri_trk_evt_get_after (pri_trk_t *trk, unsigned long type, unsigned long pos)
340{
341 pri_evt_t *evt;
342
343 evt = trk->evt;
344
345 while (evt != NULL) {
346 if ((type == PRI_EVENT_ALL) || (evt->type == type)) {
347 if (evt->pos >= pos) {
348 return (evt);
349 }
350 }
351
352 evt = evt->next;
353 }
354
355 return (NULL);
356}
357
358/*
359 * Get the last event of type <type> at or before <pos>.
360 */
361pri_evt_t *pri_trk_evt_get_before (pri_trk_t *trk, unsigned long type, unsigned long pos)
362{
363 pri_evt_t *evt, *ret;
364
365 evt = trk->evt;
366 ret = NULL;
367
368 while (evt != NULL) {
369 if ((type == PRI_EVENT_ALL) || (evt->type == type)) {
370 if (evt->pos > pos) {
371 return (ret);
372 }
373
374 ret = evt;
375 }
376
377 evt = evt->next;
378 }
379
380 return (NULL);
381}
382
383int pri_trk_evt_del (pri_trk_t *trk, pri_evt_t *evt)
384{
385 pri_evt_t *tmp, *tmp2;
386
387 if (trk->evt == NULL) {
388 return (1);
389 }
390
391 if (trk->evt == evt) {
392 tmp = trk->evt;
393 trk->evt = trk->evt->next;
394 pri_evt_del (tmp);
395 return (0);
396 }
397
398 tmp = trk->evt;
399
400 while ((tmp->next != NULL) && (tmp->next != evt)) {
401 tmp = tmp->next;
402 }
403
404 if (tmp->next == evt) {
405 tmp2 = tmp->next;
406 tmp->next = tmp2->next;
407 pri_evt_del (tmp2);
408 return (0);
409 }
410
411 return (1);
412}
413
414void pri_trk_evt_del_all (pri_trk_t *trk, unsigned long type)
415{
416 pri_evt_t *evt, *dst1, *dst2, *tmp;
417
418 evt = trk->evt;
419
420 dst1 = NULL;
421 dst2 = NULL;
422
423 while (evt != NULL) {
424 if ((type == PRI_EVENT_ALL) || (evt->type == type)) {
425 tmp = evt;
426 evt = evt->next;
427 free (tmp);
428
429 }
430 else {
431 if (dst1 == NULL) {
432 dst1 = evt;
433 }
434 else {
435 dst2->next = evt;
436 }
437
438 dst2 = evt;
439
440 evt = evt->next;
441 }
442 }
443
444 if (dst2 != NULL) {
445 dst2->next = NULL;
446 }
447
448 trk->evt = dst1;
449 trk->cur_evt = NULL;
450}
451
452unsigned pri_trk_evt_count (const pri_trk_t *trk, unsigned long type)
453{
454 unsigned cnt;
455
456 pri_evt_t *evt;
457
458 cnt = 0;
459 evt = trk->evt;
460
461 while (evt != NULL) {
462 if ((type == PRI_EVENT_ALL) || (evt->type == type)) {
463 cnt += 1;
464 }
465
466 evt = evt->next;
467 }
468
469 return (cnt);
470}
471
472/*
473 * Add ofs to all event positions, wrapping around if necessary
474 */
475static
476void pri_trk_evt_shift (pri_trk_t *trk, unsigned long ofs)
477{
478 pri_evt_t *evt, *tmp;
479
480 evt = trk->evt;
481 trk->evt = NULL;
482
483 while (evt != NULL) {
484 if (evt->pos < trk->size) {
485 evt->pos += ofs;
486
487 while (evt->pos >= trk->size) {
488 evt->pos -= trk->size;
489 }
490 }
491
492 tmp = evt;
493 evt = evt->next;
494
495 pri_trk_evt_ins (trk, tmp);
496 }
497}
498
499/*****************************************************************************
500 * Clear a track
501 *
502 * @param val An 8 bit value that is used to initialize the track
503 *****************************************************************************/
504void pri_trk_clear (pri_trk_t *trk, unsigned val)
505{
506 if (trk->size > 0) {
507 memset (trk->data, val, (trk->size + 7) / 8);
508 pri_clear_bits (trk->data, trk->size, (trk->size - 1) | 7);
509 }
510}
511
512/*****************************************************************************
513 * Clear a track
514 *
515 * @param val A 16 bit value that is used to initialize the track
516 *****************************************************************************/
517void pri_trk_clear_16 (pri_trk_t *trk, unsigned val)
518{
519 unsigned long i, n;
520 unsigned char buf[2];
521
522 if (trk->size == 0) {
523 return;
524 }
525
526 buf[0] = (val >> 8) & 0xff;
527 buf[1] = val & 0xff;
528
529 n = (trk->size + 7) / 8;
530
531 for (i = 0; i < n; i++) {
532 trk->data[i] = buf[i & 1];
533 }
534
535 pri_clear_bits (trk->data, trk->size, (trk->size - 1) | 7);
536}
537
538/*****************************************************************************
539 * Clear the remaining bits of a track
540 *****************************************************************************/
541void pri_trk_clear_slack (pri_trk_t *trk)
542{
543 if (trk->size & 7) {
544 trk->data[trk->size / 8] &= 0xff << (8 - (trk->size & 7));
545 }
546}
547
548/*****************************************************************************
549 * Set the bit rate
550 *
551 * @param clock The bit rate in Herz
552 *****************************************************************************/
553void pri_trk_set_clock (pri_trk_t *trk, unsigned long clock)
554{
555 trk->clock = clock;
556}
557
558/*****************************************************************************
559 * Get the bit rate
560 *
561 * @return The bit rate in Herz
562 *****************************************************************************/
563unsigned long pri_trk_get_clock (const pri_trk_t *trk)
564{
565 return (trk->clock);
566}
567
568/*****************************************************************************
569 * Get the track size
570 *
571 * @return The track size in bits
572 *****************************************************************************/
573unsigned long pri_trk_get_size (const pri_trk_t *trk)
574{
575 return (trk->size);
576}
577
578/*****************************************************************************
579 * Set the track size
580 *
581 * @param size The new track size in bits
582 *
583 * If the new size is greater than the old size, the new bits are
584 * initialized to 0.
585 *****************************************************************************/
586int pri_trk_set_size (pri_trk_t *trk, unsigned long size)
587{
588 unsigned long i1;
589 unsigned char *tmp;
590
591 if (trk->size == size) {
592 return (0);
593 }
594
595 trk->idx = 0;
596 trk->cur_evt = trk->evt;
597 trk->wrap = 0;
598
599 if (size == 0) {
600 free (trk->data);
601 trk->size = 0;
602 trk->data = NULL;
603 return (0);
604 }
605
606 if ((tmp = realloc (trk->data, (size + 7) / 8)) == NULL) {
607 return (1);
608 }
609
610 i1 = (size < trk->size) ? size : trk->size;
611 pri_clear_bits (tmp, i1, (size - 1) | 7);
612
613 trk->size = size;
614 trk->data = tmp;
615
616 return (0);
617}
618
619/*****************************************************************************
620 * Get the track position
621 *
622 * @return The current track position
623 *****************************************************************************/
624unsigned long pri_trk_get_pos (const pri_trk_t *trk)
625{
626 return (trk->idx);
627}
628
629/*****************************************************************************
630 * Set the track position
631 *
632 * @param pos The new track position in bits
633 *****************************************************************************/
634void pri_trk_set_pos (pri_trk_t *trk, unsigned long pos)
635{
636 if (trk->size == 0) {
637 return;
638 }
639
640 trk->idx = pos % trk->size;
641 trk->wrap = 0;
642
643 trk->cur_evt = trk->evt;
644
645 while ((trk->cur_evt != NULL) && (trk->cur_evt->pos < trk->idx)) {
646 trk->cur_evt = trk->cur_evt->next;
647 }
648}
649
650/*****************************************************************************
651 * Get bits from the current position
652 *
653 * @param val The bits, in the low order cnt bits
654 * @param cnt The number of bits (cnt <= 32)
655 *
656 * @return Non-zero if the current position wrapped around
657 *****************************************************************************/
658int pri_trk_get_bits (pri_trk_t *trk, unsigned long *val, unsigned cnt)
659{
660 unsigned long v;
661 unsigned char m;
662 const unsigned char *p;
663
664 if (trk->size == 0) {
665 *val = 0;
666 return (1);
667 }
668
669 p = trk->data + (trk->idx / 8);
670 m = 0x80 >> (trk->idx & 7);
671 v = 0;
672
673 while (cnt > 0) {
674 v = (v << 1) | ((*p & m) != 0);
675
676 m >>= 1;
677 trk->idx += 1;
678
679 if (trk->idx >= trk->size) {
680 p = trk->data;
681 m = 0x80;
682 trk->idx = 0;
683 trk->wrap = 1;
684 }
685 else if (m == 0) {
686 p += 1;
687 m = 0x80;
688 }
689
690 cnt -= 1;
691 }
692
693 *val = v;
694
695 return (trk->wrap);
696}
697
698/*****************************************************************************
699 * Set bits at the current position
700 *
701 * @param val The bits, in the low order cnt bits
702 * @param cnt The number of bits (cnt <= 32)
703 *
704 * @return Non-zero if the current position wrapped around
705 *****************************************************************************/
706int pri_trk_set_bits (pri_trk_t *trk, unsigned long val, unsigned cnt)
707{
708 unsigned char m;
709 unsigned char *p;
710
711 if (trk->size == 0) {
712 return (1);
713 }
714
715 p = trk->data + (trk->idx / 8);
716 m = 0x80 >> (trk->idx & 7);
717
718 while (cnt > 0) {
719 cnt -= 1;
720
721 if ((val >> cnt) & 1) {
722 *p |= m;
723 }
724 else {
725 *p &= ~m;
726 }
727
728 m >>= 1;
729 trk->idx += 1;
730
731 if (trk->idx >= trk->size) {
732 p = trk->data;
733 m = 0x80;
734 trk->idx = 0;
735 trk->wrap = 1;
736 }
737 else if (m == 0) {
738 p += 1;
739 m = 0x80;
740 }
741 }
742
743 return (trk->wrap);
744}
745
746/*****************************************************************************
747 * Get an event from the current position
748 *
749 * @retval type The event type
750 * @retval val The event value
751 *
752 * @return Non-zero if there are no more events at the current position
753 *****************************************************************************/
754int pri_trk_get_event (pri_trk_t *trk, unsigned long *type, unsigned long *val)
755{
756 pri_evt_t *evt;
757
758 evt = trk->cur_evt;
759
760 while ((evt != NULL) && (evt->pos < trk->idx)) {
761 evt = evt->next;
762 }
763
764 if ((evt != NULL) && (evt->pos == trk->idx)) {
765 *type = evt->type;
766 *val = evt->val;
767
768 trk->cur_evt = evt->next;
769
770 return (0);
771 }
772
773 trk->cur_evt = evt;
774
775 return (1);
776}
777
778int pri_trk_rotate (pri_trk_t *trk, unsigned long idx)
779{
780 unsigned long i;
781 unsigned char dm, sm;
782 unsigned char *sp, *dp, *tmp;
783
784 if (idx >= trk->size) {
785 return (1);
786 }
787
788 if (idx == 0) {
789 return (0);
790 }
791
792 tmp = malloc ((trk->size + 7) / 8);
793
794 if (tmp == NULL) {
795 return (1);
796 }
797
798 memset (tmp, 0, (trk->size + 7) / 8);
799
800 sp = trk->data + (idx >> 3);
801 sm = 0x80 >> (idx & 7);
802
803 dp = tmp;
804 dm = 0x80;
805
806 for (i = 0; i < trk->size; i++) {
807 if (*sp & sm) {
808 *dp |= dm;
809 }
810
811 dm >>= 1;
812
813 if (dm == 0) {
814 dp += 1;
815 dm = 0x80;
816 }
817
818 idx += 1;
819
820 if (idx >= trk->size) {
821 idx = 0;
822 sp = trk->data;
823 sm = 0x80;
824 }
825 else {
826 sm >>= 1;
827
828 if (sm == 0) {
829 sp += 1;
830 sm = 0x80;
831 }
832 }
833
834 }
835
836 free (trk->data);
837 trk->data = tmp;
838
839 pri_trk_evt_shift (trk, trk->size - idx);
840
841 return (0);
842}
843
844int pri_trk_get_weak_mask (pri_trk_t *trk, unsigned char **buf, unsigned long *cnt)
845{
846 unsigned long pos, val;
847 unsigned char *ptr;
848 pri_evt_t *evt;
849
850 *cnt = (trk->size + 7) / 8;
851
852 if ((*buf = malloc (*cnt)) == NULL) {
853 return (1);
854 }
855
856 memset (*buf, 0, *cnt);
857
858 ptr = *buf;
859
860 evt = pri_trk_evt_get_idx (trk, PRI_EVENT_WEAK, 0);
861
862 while (evt != NULL) {
863 pos = evt->pos;
864 val = evt->val;
865
866 while ((val != 0) && (pos < trk->size)) {
867 if (val & 0x80000000) {
868 ptr[pos >> 3] |= 0x80 >> (pos & 7);
869 }
870
871 pos += 1;
872 val = (val << 1) & 0xffffffff;
873 }
874
875 evt = pri_evt_next (evt, PRI_EVENT_WEAK);
876 }
877
878 return (0);
879}
880
881int pri_trk_set_weak_mask (pri_trk_t *trk, const void *buf, unsigned long cnt)
882{
883 unsigned long i, n;
884 unsigned long val;
885 const unsigned char *ptr;
886
887 n = pri_trk_get_size (trk);
888
889 if ((8 * cnt) < n) {
890 n = 8 * cnt;
891 }
892
893 pri_trk_evt_del_all (trk, PRI_EVENT_WEAK);
894
895 ptr = buf;
896 val = 0;
897
898 for (i = 0; i < n; i++) {
899 val = (val << 1) | ((ptr[i >> 3] >> (~i & 7)) & 1);
900
901 if (val & 0x80000000) {
902 pri_trk_evt_add (trk, PRI_EVENT_WEAK, i - 31, val);
903 val = 0;
904 }
905 }
906
907 while (val != 0) {
908 val = val << 1;
909
910 if (val & 0x80000000) {
911 pri_trk_evt_add (trk, PRI_EVENT_WEAK, i - 31, val);
912 val = 0;
913 }
914
915 i += 1;
916 }
917
918 return (0);
919}
920
921
922pri_cyl_t *pri_cyl_new (void)
923{
924 pri_cyl_t *cyl;
925
926 cyl = malloc (sizeof (pri_cyl_t));
927
928 if (cyl == NULL) {
929 return (NULL);
930 }
931
932 cyl->trk_cnt = 0;
933 cyl->trk = NULL;
934
935 return (cyl);
936}
937
938void pri_cyl_del (pri_cyl_t *cyl)
939{
940 unsigned long i;
941
942 if (cyl != NULL) {
943 for (i = 0; i < cyl->trk_cnt; i++) {
944 pri_trk_del (cyl->trk[i]);
945 }
946
947 free (cyl->trk);
948 free (cyl);
949 }
950}
951
952pri_cyl_t *pri_cyl_clone (const pri_cyl_t *cyl)
953{
954 unsigned long i;
955 pri_trk_t *trk;
956 pri_cyl_t *ret;
957
958 if ((ret = pri_cyl_new()) == NULL) {
959 return (NULL);
960 }
961
962 for (i = 0; i < cyl->trk_cnt; i++) {
963 if (cyl->trk[i] == NULL) {
964 continue;
965 }
966
967 if ((trk = pri_trk_clone (cyl->trk[i])) == NULL) {
968 pri_cyl_del (ret);
969 return (NULL);
970 }
971
972 if (pri_cyl_set_track (ret, trk, i)) {
973 pri_cyl_del (ret);
974 return (NULL);
975 }
976 }
977
978 return (ret);
979}
980
981unsigned long pri_cyl_get_trk_cnt (const pri_cyl_t *cyl)
982{
983 return (cyl->trk_cnt);
984}
985
986pri_trk_t *pri_cyl_get_track (pri_cyl_t *cyl, unsigned long h, int alloc)
987{
988 pri_trk_t *trk;
989
990 if ((h < cyl->trk_cnt) && (cyl->trk[h] != NULL)) {
991 return (cyl->trk[h]);
992 }
993
994 if (alloc == 0) {
995 return (NULL);
996 }
997
998 trk = pri_trk_new (0, 0);
999
1000 if (trk == NULL) {
1001 return (NULL);
1002 }
1003
1004 if (pri_cyl_set_track (cyl, trk, h)) {
1005 pri_trk_del (trk);
1006 return (NULL);
1007 }
1008
1009 return (trk);
1010}
1011
1012int pri_cyl_set_track (pri_cyl_t *cyl, pri_trk_t *trk, unsigned long h)
1013{
1014 unsigned long i;
1015 pri_trk_t **tmp;
1016
1017 if (h < cyl->trk_cnt) {
1018 pri_trk_del (cyl->trk[h]);
1019
1020 cyl->trk[h] = trk;
1021
1022 return (0);
1023 }
1024
1025 tmp = realloc (cyl->trk, (h + 1) * sizeof (pri_trk_t *));
1026
1027 if (tmp == NULL) {
1028 return (1);
1029 }
1030
1031 for (i = cyl->trk_cnt; i < h; i++) {
1032 tmp[i] = NULL;
1033 }
1034
1035 tmp[h] = trk;
1036
1037 cyl->trk = tmp;
1038 cyl->trk_cnt = h + 1;
1039
1040 return (0);
1041}
1042
1043int pri_cyl_add_track (pri_cyl_t *cyl, pri_trk_t *trk)
1044{
1045 return (pri_cyl_set_track (cyl, trk, cyl->trk_cnt));
1046}
1047
1048int pri_cyl_del_track (pri_cyl_t *cyl, unsigned long h)
1049{
1050 if ((h >= cyl->trk_cnt) || (cyl->trk[h] == NULL)) {
1051 return (1);
1052 }
1053
1054 pri_trk_del (cyl->trk[h]);
1055
1056 cyl->trk[h] = NULL;
1057
1058 while ((cyl->trk_cnt > 0) && (cyl->trk[cyl->trk_cnt - 1] == NULL)) {
1059 cyl->trk_cnt -= 1;
1060 }
1061
1062 return (0);
1063}
1064
1065
1066pri_img_t *pri_img_new (void)
1067{
1068 pri_img_t *img;
1069
1070 img = malloc (sizeof (pri_img_t));
1071
1072 if (img == NULL) {
1073 return (NULL);
1074 }
1075
1076 img->cyl_cnt = 0;
1077 img->cyl = NULL;
1078
1079 img->comment_size = 0;
1080 img->comment = NULL;
1081
1082 img->readonly = 0;
1083
1084 img->woz_track_sync = 0;
1085 img->woz_cleaned = 0;
1086
1087 return (img);
1088}
1089
1090void pri_img_del (pri_img_t *img)
1091{
1092 unsigned long i;
1093
1094 if (img != NULL) {
1095 for (i = 0; i < img->cyl_cnt; i++) {
1096 pri_cyl_del (img->cyl[i]);
1097 }
1098
1099 free (img->comment);
1100 free (img->cyl);
1101 free (img);
1102 }
1103}
1104
1105unsigned long pri_img_get_cyl_cnt (const pri_img_t *img)
1106{
1107 return (img->cyl_cnt);
1108}
1109
1110unsigned long pri_img_get_trk_cnt (const pri_img_t *img, unsigned long c)
1111{
1112 if ((c >= img->cyl_cnt) || (img->cyl[c] == NULL)) {
1113 return (0);
1114 }
1115
1116 return (img->cyl[c]->trk_cnt);
1117}
1118
1119static
1120void pri_img_fix_cyl (pri_img_t *img)
1121{
1122 while ((img->cyl_cnt > 0) && (img->cyl[img->cyl_cnt - 1] == NULL)) {
1123 img->cyl_cnt -= 1;
1124 }
1125}
1126
1127pri_cyl_t *pri_img_get_cylinder (pri_img_t *img, unsigned long c, int alloc)
1128{
1129 pri_cyl_t *cyl;
1130
1131 if ((c < img->cyl_cnt) && (img->cyl[c] != NULL)) {
1132 return (img->cyl[c]);
1133 }
1134
1135 if (alloc == 0) {
1136 return (NULL);
1137 }
1138
1139 cyl = pri_cyl_new();
1140
1141 if (cyl == NULL) {
1142 return (NULL);
1143 }
1144
1145 if (pri_img_set_cylinder (img, cyl, c)) {
1146 pri_cyl_del (cyl);
1147 return (NULL);
1148 }
1149
1150 return (cyl);
1151}
1152
1153pri_cyl_t *pri_img_rmv_cylinder (pri_img_t *img, unsigned long c)
1154{
1155 pri_cyl_t *cyl;
1156
1157 if ((c >= img->cyl_cnt) || (img->cyl[c] == NULL)) {
1158 return (NULL);
1159 }
1160
1161 cyl = img->cyl[c];
1162
1163 img->cyl[c] = NULL;
1164
1165 pri_img_fix_cyl (img);
1166
1167 return (cyl);
1168}
1169
1170int pri_img_set_cylinder (pri_img_t *img, pri_cyl_t *cyl, unsigned long c)
1171{
1172 unsigned long i;
1173 pri_cyl_t **tmp;
1174
1175 if (c < img->cyl_cnt) {
1176 pri_cyl_del (img->cyl[c]);
1177 img->cyl[c] = cyl;
1178 pri_img_fix_cyl (img);
1179
1180 return (0);
1181 }
1182
1183 tmp = realloc (img->cyl, (c + 1) * sizeof (pri_cyl_t *));
1184
1185 if (tmp == NULL) {
1186 return (1);
1187 }
1188
1189 for (i = img->cyl_cnt; i < c; i++) {
1190 tmp[i] = NULL;
1191 }
1192
1193 tmp[c] = cyl;
1194
1195 img->cyl = tmp;
1196 img->cyl_cnt = c + 1;
1197
1198 pri_img_fix_cyl (img);
1199
1200 return (0);
1201}
1202
1203int pri_img_add_cylinder (pri_img_t *img, pri_cyl_t *cyl)
1204{
1205 return (pri_img_set_cylinder (img, cyl, img->cyl_cnt));
1206}
1207
1208int pri_img_del_cylinder (pri_img_t *img, unsigned long c)
1209{
1210 if ((c >= img->cyl_cnt) || (img->cyl[c] == NULL)) {
1211 return (1);
1212 }
1213
1214 pri_cyl_del (img->cyl[c]);
1215
1216 img->cyl[c] = NULL;
1217
1218 pri_img_fix_cyl (img);
1219
1220 return (0);
1221}
1222
1223pri_trk_t *pri_img_get_track_const (const pri_img_t *img, unsigned long c, unsigned long h)
1224{
1225 pri_cyl_t *cyl;
1226
1227 if ((c >= img->cyl_cnt) || (img->cyl[c] == NULL)) {
1228 return (NULL);
1229 }
1230
1231 cyl = img->cyl[c];
1232
1233 if (h >= cyl->trk_cnt) {
1234 return (NULL);
1235 }
1236
1237 return (cyl->trk[h]);
1238}
1239
1240pri_trk_t *pri_img_get_track (pri_img_t *img, unsigned long c, unsigned long h, int alloc)
1241{
1242 pri_cyl_t *cyl;
1243 pri_trk_t *trk;
1244
1245 cyl = pri_img_get_cylinder (img, c, alloc);
1246
1247 if (cyl == NULL) {
1248 return (NULL);
1249 }
1250
1251 trk = pri_cyl_get_track (cyl, h, alloc);
1252
1253 if (trk == NULL) {
1254 return (NULL);
1255 }
1256
1257 return (trk);
1258}
1259
1260int pri_img_set_track (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h)
1261{
1262 pri_cyl_t *cyl;
1263
1264 cyl = pri_img_get_cylinder (img, c, 1);
1265
1266 if (cyl == NULL) {
1267 return (1);
1268 }
1269
1270 if (pri_cyl_set_track (cyl, trk, h)) {
1271 return (1);
1272 }
1273
1274 return (0);
1275}
1276
1277int pri_img_del_track (pri_img_t *img, unsigned long c, unsigned long h)
1278{
1279 if ((c >= img->cyl_cnt) || (img->cyl[c] == NULL)) {
1280 return (1);
1281 }
1282
1283 if (pri_cyl_del_track (img->cyl[c], h)) {
1284 return (1);
1285 }
1286
1287 return (0);
1288}
1289
1290int pri_img_add_comment (pri_img_t *img, const unsigned char *buf, unsigned cnt)
1291{
1292 unsigned char *tmp;
1293
1294 tmp = realloc (img->comment, img->comment_size + cnt);
1295
1296 if (tmp == NULL) {
1297 return (1);
1298 }
1299
1300 memcpy (tmp + img->comment_size, buf, cnt);
1301
1302 img->comment_size += cnt;
1303 img->comment = tmp;
1304
1305 return (0);
1306}
1307
1308int pri_img_set_comment (pri_img_t *img, const unsigned char *buf, unsigned cnt)
1309{
1310 free (img->comment);
1311
1312 img->comment_size = 0;
1313 img->comment = NULL;
1314
1315 if ((buf == NULL) || (cnt == 0)) {
1316 return (0);
1317 }
1318
1319 if (pri_img_add_comment (img, buf, cnt)) {
1320 return (1);
1321 }
1322
1323 return (0);
1324}
1325
1326/* Force a <nl> at the end of the comment */
1327int pri_img_add_comment_nl (pri_img_t *img)
1328{
1329 if (img->comment_size == 0) {
1330 return (0);
1331 }
1332
1333 if (img->comment[img->comment_size - 1] == 0x0a) {
1334 return (0);
1335 }
1336
1337 if (pri_img_add_comment (img, (unsigned char *) "\x0a", 1)) {
1338 return (1);
1339 }
1340
1341 return (0);
1342}