📄 handler.c
字号:
/***
* $Workfile: handler.c $
* $Revision: 1.5 $
* $Author: Dave Sewell $
* $Date: 04 May 1990 9:12:48 $
***/
/* handler.c : Alan Butt : February 1, 1989 : Expansion Box Project
This routine contains the main slave loop.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include <ctype.h>
#include "fastlynx.h"
#include "server.h"
#include "dc.h"
byte dos5_switcher = FALSE; // Set in switcher.asm
static long server_id;
static long last_client_id;
void make_server_id(void) // Called once at system init time
{
long id_value; // Start with random stack value
long _far *bios_data = (long _far *) 0x00400000L;
int i;
for (i = 0; i < 64; i++) {
id_value ^= *bios_data++;
}
*((unsigned *)&id_value) ^= fread_ticks();
*((unsigned *)&id_value + 1) ^= fread_ticks();
if (id_value == 0L)
id_value++;
server_id = id_value;
}
int server_info_handler(word count)
{
struct server_info_req request;
struct server_info_ans answer;
if ( !FxReceive(&request, sizeof(request)) )
return FALSE;
memset(&answer, '\0', sizeof(answer)); // Unused fields must be zero
answer.os_type = OS_MSDOS;
answer.developer = DEV_SEWELL;
answer.product = PRODUCT_DOSLINK;
answer.version = PRODUCT_VERSION;
answer.device_server = TRUE; // Device server supported
answer.agreed_caps.checksum = FALSE; // Can't support checksum
answer.agreed_caps.crc = TRUE; // Must use CRC
fx_max_serial_block = min(request.client_caps.max_serial_block, FxSettings.max_serial_block);
answer.agreed_caps.max_serial_block = fx_max_serial_block;
answer.last_client_id = last_client_id;
answer.server_id = server_id;
// If new master ID code, then master system must have rebooted.
// Save the new ID code and clear all auxiliary driver information
if (request.client_id != last_client_id ||
request.last_server_id != server_id) {
last_client_id = request.client_id;
reset_disk();
setup_block_devices();
}
return FxSend(&answer, sizeof(answer) -
(request.want_packets_supported ? 0 : sizeof(answer.packets_supported)) );
}
int unknown_handler(word count)
{
return FALSE;
}
/* An init packet request sends information about the block devices on this
system.
*/
int init_handler(word count)
{
register int i;
byte sp;
byte mp;
byte desired_prn_map[3];
byte desired_mapping[MAX_DEVICES];
byte avail_lpt[3];
extern byte win386_enh_mode;
config.master_dos_version = packet.init_packet_r.ipr_dos_version;
config.master_max_devices = packet.init_packet_r.ipr_max_devices;
config.master_first_unit = packet.init_packet_r.ipr_first_unit;
memcpy(desired_prn_map, packet.init_packet_r.ipr_prn_map, 3);
memcpy(desired_mapping, packet.init_packet_r.ipr_mapping, MAX_DEVICES);
// Build initial response packet
packet.init_packet_a.ipa_devices = (byte) slave_block_devices;
packet.init_packet_a.ipa_major_version = MAJOR_VERSION;
packet.init_packet_a.ipa_minor_version = MINOR_VERSION;
packet.init_packet_a.ipa_multitasker = win386_enh_mode | desqview | dos5_switcher;
packet.init_packet_a.ipa_dos_version = slave_dos_version;
make_printer_map();
memset(actual_prn_map, UNASSIGNED, 3);
memset(avail_lpt, FALSE, 3);
for (sp = 0; sp < (byte) num_lpt; sp++) {
if (printers[sp].enabled)
avail_lpt[sp] = TRUE;
}
for (mp = 0; mp < 3; mp++) { // First do hard-coded assignments
sp = desired_prn_map[mp];
if (sp < 3 && avail_lpt[sp]) {
actual_prn_map[mp] = sp;
avail_lpt[sp] = FALSE;
}
}
for (mp = 0; mp < 3; mp++) { // Then pick up the DON'T CAREs
if (desired_prn_map[mp] == DONT_CARE) {
for (sp = 0; sp < (byte) num_lpt; sp++) {
if (avail_lpt[sp]) {
actual_prn_map[mp] = sp;
avail_lpt[sp] = FALSE;
break;
}
}
}
}
memcpy(packet.init_packet_a.ipa_prn_map, actual_prn_map, 3);
generate_drive_mappings(packet.init_packet_a.ipa_mapping,
config.master_max_devices, desired_mapping);
for (i = 0; i < slave_block_devices; i++) {
packet.init_packet_a.ipa_attributes[i] = devices[i].attribute;
}
if ( !FxSend(&packet, sizeof(struct init_packet_a)) ) {
return FALSE;
}
show_drive_mappings(packet.init_packet_a.ipa_mapping, TRUE);
return TRUE;
}
/* Media Check Handler. This routine handles a media check for a given
drive.
If this is DOS 3.0+, the driver has the OCRM bit set in its attribute word,
and the media has changed, then the driver will (should) return the volume
label. This volume label will be send on to the master.
*/
int media_check_handler(word count)
{
int device;
int volume_copied = FALSE;
memset(&rhp, '\0', sizeof(rhp)); // Start with clean RHP
device = (int) packet.media_check_r.mcr_unit;
if (device >= slave_block_devices) {
rhp.media_check_ans.media_changed = MEDIA_DONT_KNOW;
rhp.s.rhp_status = STATUS_ERROR | STATUS_DONE | ERR_UNK_UNIT;
}
else {
rhp.media_check_req.s.rhp_length = 15;
rhp.media_check_req.s.rhp_unit = devices[device].unit;
rhp.media_check_req.s.rhp_command = MEDIA_CHECK;
rhp.media_check_req.media_id = packet.media_check_r.mcr_media_id;
call_driver((void far *) &rhp, devices[device].header);
if ((rhp.media_check_ans.media_changed == MEDIA_CHANGED) && _osmajor >= 3) {
volume_copied = TRUE;
memcpyf(packet.media_check_a.mca_volume, rhp.media_check_ans.media_label, MAX_VOLUME);
}
}
// Build response packet
if (!volume_copied) {
memcpyf(packet.media_check_a.mca_volume,
devices[device].volume_label, MAX_VOLUME + 4);
}
packet.media_check_a.mca_status = rhp.s.rhp_status;
packet.media_check_a.mca_changed = rhp.media_check_ans.media_changed;
// Send response packet
return FxSend(&packet, sizeof(struct media_check_a));
}
static void server_change_fail(void)
{
rhp.s.rhp_status = STATUS_ERROR | STATUS_DONE | ERR_FAILURE;
}
static int read_first_fat_sector(int device, byte media_id)
{
word sector;
if (device >= slave_block_devices) {
rhp.s.rhp_status = STATUS_ERROR | STATUS_DONE | ERR_UNK_UNIT;
rhp.io_ans.io_transfered = 0;
return FALSE;
}
rhp.io_req.s.rhp_length = sizeof(struct io_req);
rhp.io_req.s.rhp_unit = devices[device].unit;
rhp.io_req.s.rhp_command = READ;
rhp.io_req.media_id = media_id;
rhp.io_req.io_data = buffer;
rhp.io_req.io_requested = 1; // Read one sector
sector = 1; // Read sector one
if (slave_dos_version < DOS_VERSION(3, 31) ||
(devices[device].attribute & ATT_HUGE) == 0)
rhp.io_req.io_start = sector;
else if (slave_dos_version == DOS_VERSION(3, 31)) {
rhp.io_req.s.rhp_length =
(byte) ((byte *) &rhp.io_req.reserved - (byte *) &rhp);
*((dword *) &rhp.io_req.io_start) = (dword) sector;
}
else { // Else huge and > DOS 3.31
rhp.io_req.io_start = 0xFFFF;
rhp.io_req.io_huge_start = (dword) sector;
}
call_driver((void far *) &rhp, devices[device].header);
return rhp.s.rhp_status & STATUS_ERROR ? FALSE : TRUE;
}
/* Build BPB hander. This routine handles a build bpb request for a given
driver and drive.
Note: We need to save the sector size of the device.
*/
int build_bpb_handler(word count)
{
word length;
int device;
count;
device = (int) packet.build_bpb_r.bbr_unit;
if (device >= slave_block_devices) {
rhp.s.rhp_status = STATUS_ERROR | STATUS_DONE | ERR_UNK_UNIT;
}
else {
if ( (devices[device].attribute & ATT_NON_IBM) ||
read_first_fat_sector(device, packet.build_bpb_r.bbr_media_id) )
{ // not ibm format or no error reading fat
// Note: Length needs to be 22 (length of answer).
rhp.build_bpb_req.s.rhp_length = sizeof(struct build_bpb_ans);
rhp.build_bpb_req.s.rhp_unit = devices[device].unit;
rhp.build_bpb_req.s.rhp_command = BUILD_BPB;
rhp.build_bpb_req.media_id = packet.build_bpb_r.bbr_media_id;
rhp.build_bpb_req.bpb_fat = buffer;
call_driver((void far *) &rhp, devices[device].header);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -