handler.c
上传用户:xiaoan1112
上传日期:2013-04-11
资源大小:19621k
文件大小:17k
源码类别:

操作系统开发

开发平台:

Visual C++

  1. /***
  2. * $Workfile:   handler.c  $
  3. * $Revision:   1.5  $
  4. *   $Author:   Dave Sewell  $
  5. *     $Date:   04 May 1990  9:12:48  $
  6. ***/
  7. /*  handler.c : Alan Butt : February 1, 1989 : Expansion Box Project
  8.     This routine contains the main slave loop.
  9. */
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <conio.h>
  14. #include <ctype.h>
  15. #include "fastlynx.h"
  16. #include "server.h"
  17. #include "dc.h"
  18. byte dos5_switcher = FALSE;                 // Set in switcher.asm
  19. static long server_id;
  20. static long last_client_id;
  21. void make_server_id(void)                   // Called once at system init time
  22. {
  23.     long id_value;                          // Start with random stack value
  24.     long _far *bios_data = (long _far *) 0x00400000L;
  25.     int i;
  26.     for (i = 0; i < 64; i++) {
  27.         id_value ^= *bios_data++;
  28.     }
  29.     *((unsigned *)&id_value) ^= fread_ticks();
  30.     *((unsigned *)&id_value + 1) ^= fread_ticks();
  31.     if (id_value == 0L)
  32.         id_value++;
  33.     server_id = id_value;
  34. }
  35. int server_info_handler(word count)
  36. {
  37.     struct server_info_req request;
  38.     struct server_info_ans answer;
  39.     if ( !FxReceive(&request, sizeof(request)) )
  40.         return FALSE;
  41.     memset(&answer, '', sizeof(answer));      // Unused fields must be zero
  42.     answer.os_type   = OS_MSDOS;
  43.     answer.developer = DEV_SEWELL;
  44.     answer.product   = PRODUCT_DOSLINK;
  45.     answer.version   = PRODUCT_VERSION;
  46.     answer.device_server = TRUE;                // Device server supported
  47.     answer.agreed_caps.checksum = FALSE;        // Can't support checksum
  48.     answer.agreed_caps.crc      = TRUE;         // Must use CRC
  49.     fx_max_serial_block = min(request.client_caps.max_serial_block, FxSettings.max_serial_block);
  50.     answer.agreed_caps.max_serial_block = fx_max_serial_block;
  51.     answer.last_client_id = last_client_id;
  52.     answer.server_id = server_id;
  53.     // If new master ID code, then master system must have rebooted.
  54.     // Save the new ID code and clear all auxiliary driver information
  55.     if (request.client_id != last_client_id ||
  56.         request.last_server_id != server_id) {
  57.         last_client_id = request.client_id;
  58.         reset_disk();
  59.         setup_block_devices();
  60.     }
  61.     return FxSend(&answer, sizeof(answer) -
  62.         (request.want_packets_supported ? 0 : sizeof(answer.packets_supported)) );
  63. }
  64. int unknown_handler(word count)
  65. {
  66.     return FALSE;
  67. }
  68. /*  An init packet request sends information about the block devices on this
  69.     system.
  70. */
  71. int init_handler(word count)
  72. {
  73.     register int i;
  74.     byte sp;
  75.     byte mp;
  76.     byte desired_prn_map[3];
  77.     byte desired_mapping[MAX_DEVICES];
  78.     byte avail_lpt[3];
  79.     extern byte win386_enh_mode;
  80.     config.master_dos_version  = packet.init_packet_r.ipr_dos_version;
  81.     config.master_max_devices  = packet.init_packet_r.ipr_max_devices;
  82.     config.master_first_unit   = packet.init_packet_r.ipr_first_unit;
  83.     memcpy(desired_prn_map, packet.init_packet_r.ipr_prn_map, 3);
  84.     memcpy(desired_mapping, packet.init_packet_r.ipr_mapping, MAX_DEVICES);
  85.     // Build initial response packet
  86.     packet.init_packet_a.ipa_devices = (byte) slave_block_devices;
  87.     packet.init_packet_a.ipa_major_version = MAJOR_VERSION;
  88.     packet.init_packet_a.ipa_minor_version = MINOR_VERSION;
  89.     packet.init_packet_a.ipa_multitasker = win386_enh_mode | desqview | dos5_switcher;
  90.     packet.init_packet_a.ipa_dos_version = slave_dos_version;
  91.     make_printer_map();
  92.     memset(actual_prn_map, UNASSIGNED, 3);
  93.     memset(avail_lpt, FALSE, 3);
  94.     for (sp = 0; sp < (byte) num_lpt; sp++) {
  95.         if (printers[sp].enabled)
  96.             avail_lpt[sp] = TRUE;
  97.     }
  98.     for (mp = 0; mp < 3; mp++) {      // First do hard-coded assignments
  99.         sp = desired_prn_map[mp];
  100.         if (sp < 3 && avail_lpt[sp]) {
  101.             actual_prn_map[mp] = sp;
  102.             avail_lpt[sp] = FALSE;
  103.         }
  104.     }
  105.     for (mp = 0; mp < 3; mp++) {        // Then pick up the DON'T CAREs
  106.         if (desired_prn_map[mp] == DONT_CARE) {
  107.             for (sp = 0; sp < (byte) num_lpt; sp++) {
  108.                 if (avail_lpt[sp]) {
  109.                     actual_prn_map[mp] = sp;
  110.                     avail_lpt[sp] = FALSE;
  111.                     break;
  112.                 }
  113.             }
  114.         }
  115.     }
  116.     memcpy(packet.init_packet_a.ipa_prn_map, actual_prn_map, 3);
  117.     generate_drive_mappings(packet.init_packet_a.ipa_mapping,
  118.                             config.master_max_devices, desired_mapping);
  119.     for (i = 0; i < slave_block_devices; i++) {
  120.         packet.init_packet_a.ipa_attributes[i] = devices[i].attribute;
  121.     }
  122.     if ( !FxSend(&packet, sizeof(struct init_packet_a)) ) {
  123.         return FALSE;
  124.     }
  125.     show_drive_mappings(packet.init_packet_a.ipa_mapping, TRUE);
  126.     return TRUE;
  127. }
  128. /*  Media Check Handler.  This routine handles a media check for a given
  129.     drive.
  130.     If this is DOS 3.0+, the driver has the OCRM bit set in its attribute word,
  131.     and the media has changed, then the driver will (should) return the volume
  132.     label.  This volume label will be send on to the master.
  133. */
  134. int media_check_handler(word count)
  135. {
  136.     int device;
  137.     int volume_copied = FALSE;
  138.     memset(&rhp, '', sizeof(rhp));                // Start with clean RHP
  139.     device = (int) packet.media_check_r.mcr_unit;
  140.     if (device >= slave_block_devices) {
  141.         rhp.media_check_ans.media_changed = MEDIA_DONT_KNOW;
  142.         rhp.s.rhp_status = STATUS_ERROR | STATUS_DONE | ERR_UNK_UNIT;
  143.     }
  144.     else {
  145.         rhp.media_check_req.s.rhp_length = 15;
  146.         rhp.media_check_req.s.rhp_unit = devices[device].unit;
  147.         rhp.media_check_req.s.rhp_command = MEDIA_CHECK;
  148.         rhp.media_check_req.media_id = packet.media_check_r.mcr_media_id;
  149.         call_driver((void far *) &rhp, devices[device].header);
  150.         if ((rhp.media_check_ans.media_changed == MEDIA_CHANGED) && _osmajor >= 3) {
  151.             volume_copied = TRUE;
  152.             memcpyf(packet.media_check_a.mca_volume, rhp.media_check_ans.media_label, MAX_VOLUME);
  153.         }
  154.     }
  155.     // Build response packet
  156.     if (!volume_copied) {
  157.         memcpyf(packet.media_check_a.mca_volume,
  158.             devices[device].volume_label, MAX_VOLUME + 4);
  159.     }
  160.     packet.media_check_a.mca_status  = rhp.s.rhp_status;
  161.     packet.media_check_a.mca_changed = rhp.media_check_ans.media_changed;
  162.     // Send response packet
  163.     return FxSend(&packet, sizeof(struct media_check_a));
  164. }
  165. static void server_change_fail(void)
  166. {
  167.     rhp.s.rhp_status = STATUS_ERROR | STATUS_DONE | ERR_FAILURE;
  168. }
  169. static int read_first_fat_sector(int device, byte media_id)
  170. {
  171.     word sector;
  172.     if (device >= slave_block_devices) {
  173.         rhp.s.rhp_status = STATUS_ERROR | STATUS_DONE | ERR_UNK_UNIT;
  174.         rhp.io_ans.io_transfered = 0;
  175.         return FALSE;
  176.     }
  177.     rhp.io_req.s.rhp_length = sizeof(struct io_req);
  178.     rhp.io_req.s.rhp_unit = devices[device].unit;
  179.     rhp.io_req.s.rhp_command = READ;
  180.     rhp.io_req.media_id = media_id;
  181.     rhp.io_req.io_data = buffer;
  182.     rhp.io_req.io_requested = 1;        // Read one sector
  183.     sector = 1;                         // Read sector one
  184.     if (slave_dos_version < DOS_VERSION(3, 31) ||
  185.             (devices[device].attribute & ATT_HUGE) == 0)
  186.         rhp.io_req.io_start = sector;
  187.     else if (slave_dos_version == DOS_VERSION(3, 31)) {
  188.         rhp.io_req.s.rhp_length =
  189.             (byte) ((byte *) &rhp.io_req.reserved - (byte *) &rhp);
  190.         *((dword *) &rhp.io_req.io_start) = (dword) sector;
  191.     }
  192.     else {                              // Else huge and > DOS 3.31
  193.         rhp.io_req.io_start = 0xFFFF;
  194.         rhp.io_req.io_huge_start = (dword) sector;
  195.     }
  196.     call_driver((void far *) &rhp, devices[device].header);
  197.     return rhp.s.rhp_status & STATUS_ERROR ? FALSE : TRUE;
  198. }
  199. /*  Build BPB hander.  This routine handles a build bpb request for a given
  200.     driver and drive.
  201.     Note: We need to save the sector size of the device.
  202. */
  203. int build_bpb_handler(word count)
  204. {
  205.     word length;
  206.     int device;
  207.     count;
  208.     device = (int) packet.build_bpb_r.bbr_unit;
  209.     if (device >= slave_block_devices) {
  210.         rhp.s.rhp_status = STATUS_ERROR | STATUS_DONE | ERR_UNK_UNIT;
  211.     }
  212.     else {
  213.         if ( (devices[device].attribute & ATT_NON_IBM) ||
  214.              read_first_fat_sector(device, packet.build_bpb_r.bbr_media_id) )
  215.         {                  // not ibm format or no error reading fat
  216.             // Note: Length needs to be 22 (length of answer).
  217.             rhp.build_bpb_req.s.rhp_length = sizeof(struct build_bpb_ans);
  218.             rhp.build_bpb_req.s.rhp_unit = devices[device].unit;
  219.             rhp.build_bpb_req.s.rhp_command = BUILD_BPB;
  220.             rhp.build_bpb_req.media_id = packet.build_bpb_r.bbr_media_id;
  221.             rhp.build_bpb_req.bpb_fat = buffer;
  222.             call_driver((void far *) &rhp, devices[device].header);
  223.         }
  224.     }
  225.     // Build response packet
  226.     packet.build_bpb_a.bba_status = rhp.s.rhp_status;
  227.     if ( !(rhp.s.rhp_status & STATUS_ERROR) ) {     // No error building BPB
  228.         packet.build_bpb_a.bba_bpb = *rhp.build_bpb_ans.bpb_bpb;
  229.         devices[device].bytes_per_sector =
  230.             rhp.build_bpb_ans.bpb_bpb->bytes_per_sector;
  231.         length = sizeof(struct build_bpb_a);
  232.         // If media is removeable, read the volume label
  233.         if (devices[device].non_removable == FALSE) {
  234.             reset_disk();
  235.             read_volume_label(device);
  236.         }
  237.     }
  238.     else {                              // Else error getting BPB
  239.         length = (char *) &packet.build_bpb_a.bba_bpb  - (char *) &packet;
  240.     }
  241.     // Send Response Packet
  242.     if ( !FxSend(&packet, length) ) {
  243.         return FALSE;
  244.     }
  245.     devices[device].invalid = FALSE;    // Clear invalid flag after we've
  246.                                         // successfully build a BPB
  247.     return TRUE;
  248. }
  249. /*  Read request Handler.  This routine handles a read request for a given
  250.     device driver and drive.
  251.     If this is DOS 3.0+ and error ERR_DISK_CHANGE (0FH) is returned, the driver
  252.     will (should) return the volume label.
  253. */
  254. int read_handler(word count)
  255. {
  256.     word volume_length;
  257.     int device;
  258.     count;
  259.     device = (int) packet.io_r.ior_unit;
  260.     if (device >= slave_block_devices) {
  261.         rhp.s.rhp_status = STATUS_ERROR | STATUS_DONE | ERR_UNK_UNIT;
  262.     }
  263.     else {
  264.         rhp.io_req.s.rhp_length = 22;
  265.         rhp.io_req.s.rhp_unit = devices[device].unit;
  266.         rhp.io_req.s.rhp_command = READ;
  267.         rhp.io_req.media_id = packet.io_r.ior_media_id;
  268.         rhp.io_req.io_data = buffer;
  269.         rhp.io_req.io_requested = packet.io_r.ior_requested;
  270.         if (slave_dos_version != DOS_VERSION(3, 31)) {
  271.             rhp.io_req.io_start = packet.io_r.ior_start;
  272.             rhp.io_req.io_huge_start = packet.io_r.ior_huge_start;
  273.         }
  274.         else {  // else MS-DOS 3.31
  275.             rhp.io_req.s.rhp_length =
  276.                 (byte) ((byte *) &rhp.io_req.reserved - (byte *) &rhp);
  277.             *((dword *) &rhp.io_req.io_start) = packet.io_r.ior_huge_start;
  278.         }
  279.         call_driver((void far *) &rhp, devices[device].header);
  280.     }
  281.     // build response packet
  282.     packet.io_a.ioa_status = rhp.s.rhp_status;
  283.     if (rhp.s.rhp_status & STATUS_ERROR)
  284.         packet.io_a.ioa_transfered = 0;
  285.     else
  286.         packet.io_a.ioa_transfered = rhp.io_ans.io_transfered;
  287.     packet.io_a.ioa_volume[0] = '';
  288.     packet.io_a.ioa_serial_number = 0;
  289.     volume_length = 0;
  290.     if ((rhp.s.rhp_status & 0xff) == ERR_DISK_CHANGE && _osmajor >= 3) {
  291.         memcpyf(packet.io_a.ioa_volume, rhp.io_ans.io_label, MAX_VOLUME);
  292.         volume_length = MAX_VOLUME + 4;
  293.     }
  294.     // send response packet
  295.     if ( !FxSend(&packet, (packet.io_a.ioa_volume
  296.         - (char *) &packet) + volume_length) ) {
  297.         return FALSE;
  298.     }
  299.     // send data
  300.     if (rhp.io_ans.io_transfered) {
  301.         if ( !FxSend(buffer, rhp.io_ans.io_transfered *
  302.             devices[device].bytes_per_sector) ) {
  303.             return FALSE;
  304.         }
  305.     }
  306.     return TRUE;
  307. }
  308. /*  Write request Handler.  This routine handles a write request for a given
  309.     device driver and drive.
  310.     If this is DOS 3.0+ and error ERR_DISK_CHANGE (0FH) is returned, the driver
  311.     will (should) return the volume label.
  312. */
  313. int write_handler(word count)
  314. {
  315.     int device;
  316.     word bufsiz;
  317.     word volume_length;
  318.     byte command;
  319.     count;
  320.     if (packet.packet_type == WRITE_REQ) {
  321.         command = WRITE;
  322.     }
  323.     else {
  324.         command = WRITE_VERIFY;
  325.     }
  326.     // get data to be written
  327.     bufsiz = FxReceive(buffer, (word) sizeof(buffer));
  328.     if (fx_errno) { // NOTE: have to check fx_errno because bufsize can be zero
  329.         return FALSE;
  330.     }
  331.     device = (int) packet.io_r.ior_unit;
  332.     if (device >= slave_block_devices) {
  333.         rhp.s.rhp_status = STATUS_ERROR | STATUS_DONE | ERR_UNK_UNIT;
  334.         rhp.io_ans.io_transfered = 0;
  335.     }
  336.     else if (bufsiz != packet.io_r.ior_requested *
  337.         devices[device].bytes_per_sector) {
  338.         rhp.s.rhp_status = STATUS_ERROR | STATUS_DONE | ERR_WRITE_FAULT;
  339.         rhp.io_ans.io_transfered = 0;
  340.     }
  341.     else {
  342.         rhp.io_req.s.rhp_length = 22;
  343.         rhp.io_req.s.rhp_unit = devices[device].unit;
  344.         rhp.io_req.s.rhp_command = command;
  345.         rhp.io_req.media_id = packet.io_r.ior_media_id;
  346.         rhp.io_req.io_data = buffer;
  347.         rhp.io_req.io_requested = packet.io_r.ior_requested;
  348.         rhp.io_req.io_start = packet.io_r.ior_start;
  349.         rhp.io_req.io_huge_start = packet.io_r.ior_huge_start;
  350.         if (slave_dos_version == DOS_VERSION(3, 31)) {
  351.             rhp.io_req.s.rhp_length =
  352.                 (byte) ((byte *) &rhp.io_req.reserved - (byte *) &rhp);
  353.             *((dword *) &rhp.io_req.io_start) = packet.io_r.ior_huge_start;
  354.         }
  355.         call_driver((void far *) &rhp, devices[device].header);
  356.     }
  357.     // build response packet 
  358.     packet.io_a.ioa_status = rhp.s.rhp_status;
  359.     packet.io_a.ioa_transfered = rhp.io_ans.io_transfered;
  360.     packet.io_a.ioa_volume[0] = '';
  361.     packet.io_a.ioa_serial_number = 0;
  362.     volume_length = 0;
  363.     if ((rhp.s.rhp_status & 0xff) == ERR_DISK_CHANGE && _osmajor >= 3) {
  364.         memcpyf(packet.io_a.ioa_volume, rhp.io_ans.io_label, MAX_VOLUME);
  365.         volume_length = MAX_VOLUME + 4;
  366.     }
  367.     return FxSend(&packet, (packet.io_a.ioa_volume
  368.                  - (char *) &packet) + volume_length);
  369. }
  370. /*  Error Handler.  No longer used. */
  371. int error_handler(word count)
  372. {
  373.     return TRUE;
  374. }
  375. int ocrm_handler(word count)
  376. {
  377.     int device;
  378.     byte command;
  379.     count;
  380.     if (packet.packet_type == DEV_OPEN_REQ) {
  381.         command = DEVICE_OPEN;
  382.     }
  383.     else {
  384.         command = DEVICE_CLOSE;
  385.     }
  386.     device = (int) packet.ocrm_r.ocr_unit;
  387.     if (device >= slave_block_devices) {
  388.         rhp.s.rhp_status = STATUS_ERROR | STATUS_DONE | ERR_UNK_UNIT;
  389.     }
  390.     else {
  391.         rhp.s.rhp_length  = sizeof(struct static_rhp);
  392.         rhp.s.rhp_unit    = (byte) device;
  393.         rhp.s.rhp_command = command;
  394.         call_driver((void far *) &rhp, devices[device].header);
  395.     }
  396.     // build response packet
  397.     packet.ocrm_a.oca_status = rhp.s.rhp_status;
  398.     // 4) send response packet
  399.     return FxSend(&packet, sizeof(struct ocrm_a));
  400. }
  401. int gen_ioctl_handler(word count)
  402. {
  403.     int device;
  404.     struct media_id_buffer media_id_buffer;
  405.     byte function = 0;
  406.     device = (int) packet.gen_ioctl_r.gir_unit;
  407.     if (device >= slave_block_devices) {
  408.         rhp.s.rhp_status = STATUS_ERROR | STATUS_DONE | ERR_UNK_UNIT;
  409.     }
  410.     else {
  411.         function = packet.gen_ioctl_r.gir_function;
  412.         if (function == 0x46) {
  413.             if ( !FxReceive(&media_id_buffer, sizeof(media_id_buffer)) ) {
  414.                 return FALSE;
  415.             }
  416.         }
  417.         rhp.s.rhp_length  = sizeof(struct gen_ioctl_req);
  418.         rhp.s.rhp_unit    = (byte) device;
  419.         rhp.s.rhp_command = GENERIC_IOCTL;
  420.         rhp.gen_ioctl_req.gen_category = packet.gen_ioctl_r.gir_category;
  421.         rhp.gen_ioctl_req.gen_function = packet.gen_ioctl_r.gir_function;
  422.         rhp.gen_ioctl_req.gen_data = &media_id_buffer;
  423.         call_driver((void far *) &rhp, devices[device].header);
  424.     }
  425.     // build response packet
  426.     packet.gen_ioctl_a.gia_status = rhp.s.rhp_status;
  427.     // 4) send response packet
  428.     if ( !FxSend(&packet, sizeof(struct gen_ioctl_a)) ) {
  429.         return FALSE;
  430.     }
  431.     if ( (rhp.s.rhp_status & STATUS_ERROR) == 0 ) {
  432.         if (function == 0x66)
  433.             return FxSend(&media_id_buffer, sizeof(media_id_buffer));
  434.     }
  435.     return TRUE;
  436. }