fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation

mac: Add emulated DaynaPORT SCSI/Link-3 ethernet device

Currently only works on OpenBSD and requires read/write access to
the tap device (/dev/tap0 by default). A helper script is run after
bringing up the device to do things as root like assign an IP (for
NAT) or configure bridging (for ethernet).

SCSI protocol information was gleaned from the DaynaPORT driver in
RASCSI and my real DaynaPORT device.

+544 -102
+2
src/arch/macplus/Makefile.inc
··· 51 51 msg \ 52 52 rtc \ 53 53 scsi \ 54 + scsi_tap \ 54 55 serial \ 55 56 sony \ 56 57 sound \ ··· 125 126 $(rel)/msg.o: $(rel)/msg.c 126 127 $(rel)/rtc.o: $(rel)/rtc.c 127 128 $(rel)/scsi.o: $(rel)/scsi.c 129 + $(rel)/scsi_tap.o: $(rel)/scsi_tap.c 128 130 $(rel)/serial.o: $(rel)/serial.c 129 131 $(rel)/sony.o: $(rel)/sony.c 130 132 $(rel)/sound.o: $(rel)/sound.c
+29 -11
src/arch/macplus/macplus.c
··· 1081 1081 ini_sct_t *sct, *sctdev; 1082 1082 mem_blk_t *blk; 1083 1083 unsigned long addr, size; 1084 - unsigned id, drive; 1085 - const char *vendor, *product; 1084 + unsigned id, drive, ethernet; 1085 + const char *vendor, *product, *mac_addr, *tap_dev, *tap_cmd; 1086 1086 1087 1087 sct = ini_next_sct (ini, NULL, "scsi"); 1088 1088 ··· 1119 1119 while (sctdev != NULL) { 1120 1120 ini_get_uint16 (sctdev, "id", &id, 0); 1121 1121 ini_get_uint16 (sctdev, "drive", &drive, 0); 1122 - ini_get_string (sctdev, "vendor", &vendor, "PCE"); 1123 - ini_get_string (sctdev, "product", &product, "PCEDISK"); 1122 + ini_get_uint16 (sctdev, "ethernet", &ethernet, 0); 1124 1123 1125 - pce_log_tag (MSG_INF, 1126 - "SCSI:", "id=%u drive=%u vendor=\"%s\" product=\"%s\"\n", 1127 - id, drive, vendor, product 1128 - ); 1124 + if (drive) { 1125 + ini_get_string (sctdev, "vendor", &vendor, "PCE"); 1126 + ini_get_string (sctdev, "product", &product, "PCEDISK"); 1129 1127 1130 - mac_scsi_set_drive (&sim->scsi, id, drive); 1131 - mac_scsi_set_drive_vendor (&sim->scsi, id, vendor); 1132 - mac_scsi_set_drive_product (&sim->scsi, id, product); 1128 + pce_log_tag (MSG_INF, 1129 + "SCSI:", 1130 + "id=%u drive=%u vendor=\"%s\" product=\"%s\"\n", 1131 + id, drive, vendor, product 1132 + ); 1133 + 1134 + mac_scsi_set_drive (&sim->scsi, id, drive); 1135 + mac_scsi_set_drive_vendor (&sim->scsi, id, vendor); 1136 + mac_scsi_set_drive_product (&sim->scsi, id, product); 1137 + } 1138 + else if (ethernet) { 1139 + ini_get_string (sctdev, "tap", &tap_dev, "/dev/tap0"); 1140 + ini_get_string (sctdev, "tap_cmd", &tap_cmd, ""); 1141 + ini_get_string (sctdev, "mac_addr", &mac_addr, "00:80:19:c0:ff:ee"); 1142 + 1143 + pce_log_tag (MSG_INF, 1144 + "SCSI:", 1145 + "id=%u ethernet=%u tap=%s cmd=%s mac_addr=%s\n", 1146 + id, ethernet, tap_dev, tap_cmd, mac_addr 1147 + ); 1148 + 1149 + mac_scsi_set_ethernet (&sim->scsi, id, tap_dev, tap_cmd, mac_addr); 1150 + } 1133 1151 1134 1152 sctdev = ini_next_sct (sct, sctdev, "device"); 1135 1153 }
+17
src/arch/macplus/pce-macplus.cfg.in
··· 284 284 id = 2 285 285 drive = 130 286 286 } 287 + 288 + # DaynaPORT SCSI/Link device emulation on SCSI id 3. 289 + # Requires read/write access on the "tap" device listed here. 290 + #device { 291 + # id = 3 292 + # ethernet = 1 293 + # tap = "/dev/tap0" # OpenBSD 294 + # tap = "/dev/net/tun" # Linux 295 + # mac_addr = "00:80:19:c0:ff:ee" 296 + # 297 + # # This command will be run after initializing the tap device 298 + # # and will have the tap device and MAC address passed as 299 + # # arguments. It should probably assign an IP to this tap 300 + # # device if using NAT (required on WiFi), or setup bridging 301 + # # if using ethernet. 302 + # tap_cmd = "sh /etc/pce/tap-setup.sh" 303 + #} 287 304 } 288 305 289 306
+374 -91
src/arch/macplus/scsi.c
··· 30 30 31 31 #include <drivers/block/block.h> 32 32 33 + #include <lib/log.h> 34 + 33 35 34 36 /* ICR 1 */ 35 37 #define E5380_ICR_RST 0x80 ··· 149 151 150 152 scsi->dev[id].valid = 1; 151 153 scsi->dev[id].drive = drive; 154 + scsi->dev[id].type = MAC_SCSI_DEV_DISK; 152 155 153 156 memcpy (scsi->dev[id].vendor, "PCE ", 8); 154 157 memcpy (scsi->dev[id].product, "PCEDISK ", 16); ··· 185 188 else { 186 189 dst[i] = *(product++); 187 190 } 191 + } 192 + } 193 + 194 + void mac_scsi_set_ethernet (mac_scsi_t *scsi, unsigned id, const char *tap_dev, const char *tap_cmd, const char *mac_addr) 195 + { 196 + int mac_addr_ints[6]; 197 + int ret; 198 + 199 + id &= 7; 200 + 201 + scsi->dev[id].valid = 0; 202 + scsi->dev[id].type = MAC_SCSI_DEV_ETHERNET; 203 + 204 + memcpy (scsi->dev[id].vendor, "Dayna ", 8); 205 + memcpy (scsi->dev[id].product, "SCSI/Link ", 16); 206 + memcpy (scsi->dev[id].revision, "2.0f", 4); 207 + 208 + strlcpy (scsi->dev[id].tap_dev, tap_dev, sizeof(scsi->dev[id].tap_dev)); 209 + strlcpy (scsi->dev[id].tap_cmd, tap_cmd, sizeof(scsi->dev[id].tap_cmd)); 210 + 211 + ret = sscanf(mac_addr, "%x:%x:%x:%x:%x:%x", 212 + &mac_addr_ints[0], &mac_addr_ints[1], 213 + &mac_addr_ints[2], &mac_addr_ints[3], 214 + &mac_addr_ints[4], &mac_addr_ints[5]); 215 + if (ret == 6) { 216 + for (int i = 0; i <= 5; i++) 217 + scsi->dev[id].mac_addr[i] = mac_addr_ints[i] & 0xff; 218 + } else { 219 + pce_log (MSG_ERR, "*** invalid MAC address (%s)\n", mac_addr); 220 + } 221 + 222 + if (mac_scsi_ethernet_tap_open (scsi, &scsi->dev[id]) == 0) { 223 + scsi->dev[id].valid = 1; 188 224 } 189 225 } 190 226 ··· 463 499 static 464 500 void mac_scsi_cmd_read (mac_scsi_t *scsi, unsigned long lba, unsigned long cnt) 465 501 { 466 - disk_t *dsk; 502 + mac_scsi_dev_t *dev; 503 + disk_t *dsk; 504 + int psize; 467 505 468 - dsk = mac_scsi_get_disk (scsi); 506 + dev = mac_scsi_get_device (scsi); 469 507 470 - if (dsk == NULL) { 508 + if (dev == NULL) { 471 509 mac_scsi_set_phase_status (scsi, 0x02); 472 510 return; 473 511 } 474 512 513 + switch (dev->type) { 514 + case MAC_SCSI_DEV_DISK: 515 + dsk = mac_scsi_get_disk (scsi); 516 + 517 + if (dsk == NULL) { 518 + mac_scsi_set_phase_status (scsi, 0x02); 519 + return; 520 + } 521 + 475 522 #ifdef DEBUG_SCSI 476 - mac_log_deb ("scsi: read %u blocks at %lu\n", cnt, lba); 523 + mac_log_deb ("scsi: read %u blocks at %lu\n", cnt, lba); 477 524 #endif 478 525 479 - if (mac_scsi_set_buf_max (scsi, 512UL * cnt)) { 480 - mac_log_deb ("scsi: too many blocks (%u)\n", cnt); 481 - mac_scsi_set_phase_status (scsi, 0x02); 482 - return; 483 - } 526 + if (mac_scsi_set_buf_max (scsi, 512UL * cnt)) { 527 + mac_log_deb ("scsi: too many blocks (%u)\n", cnt); 528 + mac_scsi_set_phase_status (scsi, 0x02); 529 + return; 530 + } 531 + 532 + if (dsk_read_lba (dsk, scsi->buf, lba, cnt)) { 533 + mac_log_deb ("scsi: read error at %lu + %lu\n", lba, cnt); 534 + mac_scsi_set_phase_status (scsi, 0x02); 535 + return; 536 + } 484 537 485 - if (dsk_read_lba (dsk, scsi->buf, lba, cnt)) { 486 - mac_log_deb ("scsi: read error at %lu + %lu\n", lba, cnt); 487 - mac_scsi_set_phase_status (scsi, 0x02); 488 - return; 489 - } 538 + scsi->buf_i = 0; 539 + scsi->buf_n = 512 * cnt; 490 540 491 - scsi->buf_i = 0; 492 - scsi->buf_n = 512 * cnt; 541 + mac_scsi_set_phase_data_in (scsi); 542 + break; 543 + case MAC_SCSI_DEV_ETHERNET: 544 + if (cnt == 1) { 545 + mac_scsi_set_phase_status (scsi, 0x02); 546 + return; 547 + } 493 548 494 - mac_scsi_set_phase_data_in (scsi); 549 + cnt = 1514 + 6; 550 + 551 + if (mac_scsi_set_buf_max (scsi, cnt)) { 552 + mac_scsi_set_phase_status (scsi, 0x02); 553 + return; 554 + } 555 + 556 + memset (scsi->buf, 0, cnt); 557 + 558 + psize = mac_scsi_ethernet_read (dev, scsi->buf + 6); 559 + if (psize > 0) { 560 + scsi->buf[0] = (psize >> 8) & 0xff; 561 + scsi->buf[1] = psize & 0xff; 562 + 563 + if (mac_scsi_ethernet_data_avail (dev)) { 564 + scsi->buf[5] = 0x10; 565 + } 566 + } 567 + 568 + scsi->buf_i = 0; 569 + scsi->buf_n = psize + 6; 570 + 571 + mac_scsi_set_phase_data_in (scsi); 572 + break; 573 + } 495 574 } 496 575 497 576 static ··· 536 615 static 537 616 void mac_scsi_cmd_write_finish (mac_scsi_t *scsi, unsigned long lba, unsigned long cnt) 538 617 { 539 - disk_t *dsk; 618 + mac_scsi_dev_t *dev; 619 + disk_t *dsk; 540 620 541 - dsk = mac_scsi_get_disk (scsi); 621 + dev = mac_scsi_get_device (scsi); 542 622 543 - if (dsk == NULL) { 623 + if (dev == NULL) { 544 624 mac_scsi_set_phase_status (scsi, 0x02); 545 625 return; 546 626 } 547 627 548 - if ((512 * cnt) != scsi->buf_i) { 549 - mac_log_deb ("scsi: write size mismatch (%u / %u)\n", 550 - 512 * cnt, scsi->buf_i 551 - ); 552 - mac_scsi_set_phase_status (scsi, 0x02); 553 - return; 554 - } 628 + switch (dev->type) { 629 + case MAC_SCSI_DEV_DISK: 630 + dsk = mac_scsi_get_disk (scsi); 631 + 632 + if (dsk == NULL) { 633 + mac_scsi_set_phase_status (scsi, 0x02); 634 + return; 635 + } 636 + 637 + if ((512 * cnt) != scsi->buf_i) { 638 + mac_log_deb ("scsi: write size mismatch (%u / %u)\n", 639 + 512 * cnt, scsi->buf_i 640 + ); 641 + mac_scsi_set_phase_status (scsi, 0x02); 642 + return; 643 + } 555 644 556 645 #ifdef DEBUG_SCSI 557 - mac_log_deb ("scsi: write %u blocks at %lu\n", cnt, lba); 646 + mac_log_deb ("scsi: write %u blocks at %lu\n", cnt, lba); 558 647 #endif 559 648 560 - if (dsk_write_lba (dsk, scsi->buf, lba, cnt)) { 561 - mac_log_deb ("scsi: write error\n"); 562 - mac_scsi_set_phase_status (scsi, 0x02); 563 - return; 649 + if (dsk_write_lba (dsk, scsi->buf, lba, cnt)) { 650 + mac_log_deb ("scsi: write error\n"); 651 + mac_scsi_set_phase_status (scsi, 0x02); 652 + return; 653 + } 654 + break; 655 + case MAC_SCSI_DEV_ETHERNET: 656 + if (scsi->cmd[5] == 0x80) { 657 + mac_scsi_ethernet_write (dev, scsi->buf + 4, cnt); 658 + } else { 659 + mac_scsi_ethernet_write (dev, scsi->buf, cnt); 660 + } 661 + break; 564 662 } 565 663 566 664 scsi->buf_i = 0; ··· 594 692 static 595 693 void mac_scsi_cmd_write6 (mac_scsi_t *scsi) 596 694 { 597 - unsigned cnt; 695 + mac_scsi_dev_t *dev; 696 + unsigned long size; 697 + unsigned cnt; 698 + 699 + dev = mac_scsi_get_device (scsi); 700 + 701 + if (dev == NULL) { 702 + mac_scsi_set_phase_status (scsi, 0x02); 703 + return; 704 + } 598 705 599 706 cnt = scsi->cmd[4]; 600 707 ··· 602 709 cnt = 256; 603 710 } 604 711 605 - if (mac_scsi_set_buf_max (scsi, 512UL * cnt)) { 712 + switch (dev->type) { 713 + case MAC_SCSI_DEV_DISK: 714 + size = 512UL * cnt; 715 + break; 716 + 717 + case MAC_SCSI_DEV_ETHERNET: 718 + size = scsi->cmd[4] + (scsi->cmd[3] << 8); 719 + if (scsi->cmd[5] == 0x80) { 720 + size += 8; 721 + } 722 + break; 723 + } 724 + 725 + if (mac_scsi_set_buf_max (scsi, size)) { 606 726 mac_log_deb ("scsi: write block count %u\n", cnt); 607 727 mac_scsi_set_phase_status (scsi, 0x02); 608 728 return; 609 729 } 610 730 611 731 scsi->buf_i = 0; 612 - scsi->buf_n = 512 * cnt; 732 + scsi->buf_n = size; 613 733 614 734 scsi->cmd_finish = mac_scsi_cmd_write6_finish; 615 735 ··· 658 778 static 659 779 void mac_scsi_cmd_verify10 (mac_scsi_t *scsi) 660 780 { 661 - unsigned long lba; 662 - unsigned cnt; 663 - disk_t *dsk; 781 + mac_scsi_dev_t *dev; 782 + unsigned long lba; 783 + unsigned cnt; 784 + disk_t *dsk; 664 785 665 - dsk = mac_scsi_get_disk (scsi); 786 + dev = mac_scsi_get_device (scsi); 666 787 667 - if (dsk == NULL) { 788 + if (dev == NULL) { 668 789 mac_scsi_set_phase_status (scsi, 0x02); 669 790 return; 670 791 } 671 792 672 - /* lun = (scsi->cmd[1] >> 5) & 0x07; */ 793 + switch (dev->type) { 794 + case MAC_SCSI_DEV_DISK: 795 + dsk = mac_scsi_get_disk (scsi); 796 + 797 + if (dsk == NULL) { 798 + mac_scsi_set_phase_status (scsi, 0x02); 799 + return; 800 + } 801 + 802 + /* lun = (scsi->cmd[1] >> 5) & 0x07; */ 673 803 674 - lba = scsi->cmd[2]; 675 - lba = (lba << 8) | scsi->cmd[3]; 676 - lba = (lba << 8) | scsi->cmd[4]; 677 - lba = (lba << 8) | scsi->cmd[5]; 804 + lba = scsi->cmd[2]; 805 + lba = (lba << 8) | scsi->cmd[3]; 806 + lba = (lba << 8) | scsi->cmd[4]; 807 + lba = (lba << 8) | scsi->cmd[5]; 678 808 679 - cnt = scsi->cmd[7]; 680 - cnt = (cnt << 8) | scsi->cmd[8]; 809 + cnt = scsi->cmd[7]; 810 + cnt = (cnt << 8) | scsi->cmd[8]; 681 811 682 812 #ifdef DEBUG_SCSI 683 - mac_log_deb ("scsi: verify %u blocks at %lu\n", cnt, lba); 813 + mac_log_deb ("scsi: verify %u blocks at %lu\n", cnt, lba); 684 814 #endif 815 + break; 816 + case MAC_SCSI_DEV_ETHERNET: 817 + break; 818 + } 685 819 686 820 scsi->buf_i = 0; 687 821 scsi->buf_n = 0; ··· 701 835 if (dev != NULL) { 702 836 memcpy (scsi->buf + 8, dev->vendor, 8); 703 837 memcpy (scsi->buf + 16, dev->product, 16); 838 + memcpy (scsi->buf + 32, dev->revision, 4); 839 + 840 + switch (dev->type) { 841 + case MAC_SCSI_DEV_DISK: 842 + scsi->buf[0] = 0x00; /* direct-access device */ 843 + break; 844 + 845 + case MAC_SCSI_DEV_ETHERNET: 846 + scsi->buf[0] = 0x03; /* processor device */ 847 + scsi->buf[2] = 0x01; 848 + break; 849 + } 704 850 } 705 851 706 852 scsi->buf[4] = 32; ··· 723 869 static 724 870 void mac_scsi_cmd_mode_sense (mac_scsi_t *scsi) 725 871 { 726 - disk_t *dsk; 872 + mac_scsi_dev_t *dev; 873 + disk_t *dsk; 727 874 728 - dsk = mac_scsi_get_disk (scsi); 875 + dev = mac_scsi_get_device (scsi); 729 876 730 - if (dsk == NULL) { 877 + if (dev == NULL) { 731 878 mac_scsi_set_phase_status (scsi, 0x02); 732 879 return; 733 880 } 734 881 735 - memset (scsi->buf, 0, 512); 882 + switch (dev->type) { 883 + case MAC_SCSI_DEV_DISK: 884 + dsk = mac_scsi_get_disk (scsi); 736 885 737 - scsi->buf_i = 0; 738 - scsi->buf_n = 0; 886 + if (dsk == NULL) { 887 + mac_scsi_set_phase_status (scsi, 0x02); 888 + return; 889 + } 739 890 740 - switch (scsi->cmd[2] & 0x3f) { 741 - case 0x01: /* read-write error recovery page */ 742 - scsi->buf[0] = 0x01; 743 - scsi->buf[1] = 10; 744 - scsi->buf_n = 12; 745 - break; 891 + memset (scsi->buf, 0, 512); 892 + 893 + scsi->buf_i = 0; 894 + scsi->buf_n = 0; 895 + 896 + switch (scsi->cmd[2] & 0x3f) { 897 + case 0x01: /* read-write error recovery page */ 898 + scsi->buf[0] = 0x01; 899 + scsi->buf[1] = 10; 900 + scsi->buf_n = 12; 901 + break; 902 + 903 + case 0x03: /* format device page */ 904 + scsi->buf[0] = 0x03; 905 + scsi->buf[1] = 22; 906 + scsi->buf_n = 24; 907 + break; 746 908 747 - case 0x03: /* format device page */ 748 - scsi->buf[0] = 0x03; 749 - scsi->buf[1] = 22; 750 - scsi->buf_n = 24; 751 - break; 909 + case 0x04: /* rigid disk drive geometry page */ 910 + scsi->buf[0] = 0x04; 911 + scsi->buf[1] = 22; 912 + scsi->buf[2] = 0; 913 + buf_set_uint16_be (scsi->buf, 3, dsk->c); 914 + scsi->buf[5] = dsk->h; 915 + buf_set_uint16_be (scsi->buf, 20, 3600); 916 + scsi->buf_n = 32; 917 + break; 752 918 753 - case 0x04: /* rigid disk drive geometry page */ 754 - scsi->buf[0] = 0x04; 755 - scsi->buf[1] = 22; 756 - scsi->buf[2] = 0; 757 - buf_set_uint16_be (scsi->buf, 3, dsk->c); 758 - scsi->buf[5] = dsk->h; 759 - buf_set_uint16_be (scsi->buf, 20, 3600); 760 - scsi->buf_n = 32; 761 - break; 919 + case 0x30: /* vendor specific */ 920 + scsi->buf[0] = 0x30; 921 + scsi->buf[1] = 33; 922 + strcpy ((char *) scsi->buf + 14, "APPLE COMPUTER, INC"); 923 + scsi->buf_n = 34; 924 + break; 762 925 763 - case 0x30: /* vendor specific */ 764 - scsi->buf[0] = 0x30; 765 - scsi->buf[1] = 33; 766 - strcpy ((char *) scsi->buf + 14, "APPLE COMPUTER, INC"); 767 - scsi->buf_n = 34; 926 + default: 927 + mac_log_deb ("scsi: mode sense: unknown mode page (%02X)\n", 928 + scsi->cmd[2] 929 + ); 930 + break; 931 + } 768 932 break; 769 933 770 - default: 771 - mac_log_deb ("scsi: mode sense: unknown mode page (%02X)\n", 772 - scsi->cmd[2] 773 - ); 934 + case MAC_SCSI_DEV_ETHERNET: 774 935 break; 775 936 } 776 937 ··· 810 971 static 811 972 void mac_scsi_cmd_read_capacity (mac_scsi_t *scsi) 812 973 { 813 - unsigned long cnt; 814 - disk_t *dsk; 974 + unsigned long cnt; 975 + mac_scsi_dev_t *dev; 976 + disk_t *dsk; 815 977 816 - dsk = mac_scsi_get_disk (scsi); 978 + dev = mac_scsi_get_device (scsi); 817 979 818 - if (dsk == NULL) { 980 + if (dev == NULL) { 819 981 mac_scsi_set_phase_status (scsi, 0x02); 820 982 return; 821 983 } 822 984 823 - cnt = dsk_get_block_cnt (dsk); 824 - buf_set_uint32_be (scsi->buf, 0, cnt - 1); 825 - buf_set_uint32_be (scsi->buf, 4, 512); 985 + switch (dev->type) { 986 + case MAC_SCSI_DEV_DISK: 987 + dsk = mac_scsi_get_disk (scsi); 988 + 989 + if (dsk == NULL) { 990 + mac_scsi_set_phase_status (scsi, 0x02); 991 + return; 992 + } 993 + 994 + cnt = dsk_get_block_cnt (dsk); 995 + buf_set_uint32_be (scsi->buf, 0, cnt - 1); 996 + buf_set_uint32_be (scsi->buf, 4, 512); 997 + break; 998 + 999 + case MAC_SCSI_DEV_ETHERNET: 1000 + buf_set_uint32_be (scsi->buf, 0, 1); 1001 + buf_set_uint32_be (scsi->buf, 4, 512); 1002 + break; 1003 + } 826 1004 827 1005 scsi->buf_i = 0; 828 1006 scsi->buf_n = 8; ··· 842 1020 } 843 1021 844 1022 1023 + /* DaynaPort vendor commands */ 1024 + 1025 + static 1026 + void mac_scsi_cmd_read_stats (mac_scsi_t *scsi) 1027 + { 1028 + mac_scsi_dev_t *dev; 1029 + 1030 + dev = mac_scsi_get_device (scsi); 1031 + 1032 + if (dev == NULL || dev->type != MAC_SCSI_DEV_ETHERNET) { 1033 + mac_scsi_set_phase_status (scsi, 0x02); 1034 + return; 1035 + } 1036 + 1037 + memset (scsi->buf, 0, 18); 1038 + 1039 + memcpy(scsi->buf, dev->mac_addr, 6); 1040 + /* three 32-bit counters expected to follow, just return zero for all */ 1041 + 1042 + scsi->buf_i = 0; 1043 + scsi->buf_n = 18; 1044 + 1045 + mac_scsi_set_phase_data_in (scsi); 1046 + } 1047 + 1048 + static 1049 + void mac_scsi_cmd_set_interface_mode (mac_scsi_t *scsi) 1050 + { 1051 + mac_scsi_dev_t *dev; 1052 + unsigned char cmd; 1053 + 1054 + dev = mac_scsi_get_device (scsi); 1055 + 1056 + if (dev == NULL || dev->type != MAC_SCSI_DEV_ETHERNET) { 1057 + mac_scsi_set_phase_status (scsi, 0x02); 1058 + return; 1059 + } 1060 + 1061 + cmd = scsi->cmd[5] & 0x80; 1062 + 1063 + switch (cmd) { 1064 + case 0x40: 1065 + /* set MAC */ 1066 + break; 1067 + 1068 + case 0x80: 1069 + /* set mode */ 1070 + break; 1071 + 1072 + default: 1073 + mac_log_deb ("scsi: unknown interface mode command (%02X)\n", cmd); 1074 + } 1075 + 1076 + mac_scsi_set_phase_status (scsi, 0x02); 1077 + } 1078 + 1079 + static 1080 + void mac_scsi_cmd_set_mcast_addr (mac_scsi_t *scsi) 1081 + { 1082 + mac_scsi_dev_t *dev; 1083 + 1084 + dev = mac_scsi_get_device (scsi); 1085 + 1086 + if (dev == NULL || dev->type != MAC_SCSI_DEV_ETHERNET) { 1087 + mac_scsi_set_phase_status (scsi, 0x02); 1088 + return; 1089 + } 1090 + 1091 + mac_scsi_set_phase_status (scsi, 0x02); 1092 + } 1093 + 1094 + static 1095 + void mac_scsi_cmd_enable_interface (mac_scsi_t *scsi) 1096 + { 1097 + mac_scsi_dev_t *dev; 1098 + 1099 + dev = mac_scsi_get_device (scsi); 1100 + 1101 + if (dev == NULL || dev->type != MAC_SCSI_DEV_ETHERNET) { 1102 + mac_scsi_set_phase_status (scsi, 0x02); 1103 + return; 1104 + } 1105 + 1106 + dev->tap_enabled = !!(scsi->cmd[5] & 0x80); 1107 + 1108 + mac_scsi_set_phase_status (scsi, 0x02); 1109 + } 1110 + 1111 + 845 1112 static 846 1113 void mac_scsi_set_cmd (mac_scsi_t *scsi, unsigned cnt, void (*cmd) (mac_scsi_t *scsi)) 847 1114 { ··· 872 1139 mac_scsi_set_cmd (scsi, 6, mac_scsi_cmd_read6); 873 1140 break; 874 1141 1142 + case 0x09: 1143 + mac_scsi_set_cmd (scsi, 6, mac_scsi_cmd_read_stats); 1144 + break; 1145 + 875 1146 case 0x0a: 876 1147 mac_scsi_set_cmd (scsi, 6, mac_scsi_cmd_write6); 1148 + break; 1149 + 1150 + case 0x0c: 1151 + mac_scsi_set_cmd (scsi, 6, mac_scsi_cmd_set_interface_mode); 1152 + break; 1153 + 1154 + case 0x0d: 1155 + mac_scsi_set_cmd (scsi, 6, mac_scsi_cmd_set_mcast_addr); 1156 + break; 1157 + 1158 + case 0x0e: 1159 + mac_scsi_set_cmd (scsi, 6, mac_scsi_cmd_enable_interface); 877 1160 break; 878 1161 879 1162 case 0x12: ··· 1224 1507 1225 1508 scsi->icr &= ~E5380_ICR_BSY; 1226 1509 1227 - if (mac_scsi_get_disk (scsi) != NULL) { 1510 + if (mac_scsi_get_device (scsi) != NULL) { 1228 1511 mac_scsi_set_phase_cmd (scsi); 1229 1512 mac_scsi_set_int (scsi, 1); 1230 1513 }
+21
src/arch/macplus/scsi.h
··· 24 24 #define PCE_MACPLUS_SCSI_H 1 25 25 26 26 27 + #include <limits.h> 28 + 27 29 #include <drivers/block/block.h> 28 30 31 + enum { 32 + MAC_SCSI_DEV_UNKNOWN, 33 + MAC_SCSI_DEV_DISK, 34 + MAC_SCSI_DEV_ETHERNET, 35 + }; 29 36 30 37 typedef struct { 31 38 int valid; 32 39 40 + int type; 41 + 33 42 /* the PCE drive number */ 34 43 unsigned drive; 35 44 36 45 unsigned char vendor[8]; 37 46 unsigned char product[16]; 47 + unsigned char revision[4]; 48 + 49 + int tap_enabled; 50 + unsigned char mac_addr[6]; 51 + char tap_dev[PATH_MAX]; 52 + char tap_cmd[PATH_MAX]; 53 + int tap_fd; 38 54 } mac_scsi_dev_t; 39 55 40 56 ··· 89 105 void mac_scsi_set_drive (mac_scsi_t *scsi, unsigned id, unsigned drive); 90 106 void mac_scsi_set_drive_vendor (mac_scsi_t *scsi, unsigned id, const char *vendor); 91 107 void mac_scsi_set_drive_product (mac_scsi_t *scsi, unsigned id, const char *product); 108 + void mac_scsi_set_ethernet (mac_scsi_t *scsi, unsigned id, const char *tap_dev, const char *tap_cmd, const char *mac_addr); 92 109 93 110 unsigned char mac_scsi_get_uint8 (void *ext, unsigned long addr); 94 111 unsigned short mac_scsi_get_uint16 (void *ext, unsigned long addr); ··· 98 115 99 116 void mac_scsi_reset (mac_scsi_t *scsi); 100 117 118 + int mac_scsi_ethernet_tap_open (mac_scsi_t *scsi, mac_scsi_dev_t *dev); 119 + int mac_scsi_ethernet_data_avail (mac_scsi_dev_t *dev); 120 + size_t mac_scsi_ethernet_read (mac_scsi_dev_t *dev, unsigned char *buf); 121 + size_t mac_scsi_ethernet_write (mac_scsi_dev_t *dev, unsigned char *buf, size_t len); 101 122 102 123 #endif
+101
src/arch/macplus/scsi_tap.c
··· 1 + /***************************************************************************** 2 + * pce * 3 + *****************************************************************************/ 4 + 5 + /***************************************************************************** 6 + * File name: src/arch/macplus/scsi_tap.c * 7 + * Created: 2022-05-01 by joshua stein <jcs@jcs.org> * 8 + * Copyright: (C) 2022 joshua stein <jcs@jcs.org> * 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 + #include "main.h" 23 + #include "scsi.h" 24 + 25 + #include <stdlib.h> 26 + 27 + #include <lib/log.h> 28 + 29 + #include <errno.h> 30 + #include <string.h> 31 + #include <poll.h> 32 + #include <sys/fcntl.h> 33 + #include <sys/types.h> 34 + int mac_scsi_ethernet_tap_open (mac_scsi_t *scsi, mac_scsi_dev_t *dev) 35 + { 36 + char tap_cmd_sh[1024]; 37 + 38 + dev->tap_fd = -1; 39 + 40 + if ((dev->tap_fd = open (dev->tap_dev, O_RDWR)) < 0) { 41 + pce_log (MSG_ERR, "*** opening %s failed (%s)\n", dev->tap_dev, strerror(errno)); 42 + return - 1; 43 + } 44 + 45 + if (dev->tap_cmd[0] != '\0') { 46 + /* run command with args "/dev/tap0" "00:00:00:00:00:00" */ 47 + snprintf (tap_cmd_sh, sizeof(tap_cmd_sh), "%s \"%s\" \"%02x:%02x:%02x:%02x:%02x:%02x\"", 48 + dev->tap_cmd, dev->tap_dev, 49 + dev->mac_addr[0], dev->mac_addr[1], 50 + dev->mac_addr[2], dev->mac_addr[3], 51 + dev->mac_addr[4], dev->mac_addr[5]); 52 + pce_log_tag (MSG_INF, 53 + "SCSI:", 54 + "running tap command: %s\n", 55 + tap_cmd_sh); 56 + 57 + if (system (tap_cmd_sh) != 0) { 58 + pce_log (MSG_ERR, "*** tap command failed (%s)\n", strerror(errno)); 59 + } 60 + } 61 + 62 + return 0; 63 + } 64 + 65 + int mac_scsi_ethernet_data_avail (mac_scsi_dev_t *dev) 66 + { 67 + struct pollfd fds; 68 + 69 + fds.fd = dev->tap_fd; 70 + fds.events = POLLIN | POLLERR; 71 + if (poll (&fds, 1, 0) < 1) { 72 + return 0; 73 + } 74 + if ((fds.revents & POLLIN)) { 75 + return 1; 76 + } 77 + 78 + return 0; 79 + } 80 + 81 + size_t mac_scsi_ethernet_read (mac_scsi_dev_t *dev, unsigned char *buf) 82 + { 83 + if (dev->tap_fd < 0) { 84 + return 0; 85 + } 86 + 87 + if (!mac_scsi_ethernet_data_avail (dev)) { 88 + return 0; 89 + } 90 + 91 + return read (dev->tap_fd, buf, 1514); 92 + } 93 + 94 + size_t mac_scsi_ethernet_write (mac_scsi_dev_t *dev, unsigned char *buf, size_t len) 95 + { 96 + if (dev->tap_fd < 0) { 97 + return 0; 98 + } 99 + 100 + return write (dev->tap_fd, buf, len); 101 + }