fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 1342 lines 24 kB view raw
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}