This is parallel.c in view mode; [Download] [Up]
/* * parallel.c - IEEE488 emulation. * * Written by * André Fachat (a.fachat@physik.tu-chemnitz.de) * * This file is part of VICE, the Versatile Commodore Emulator. * See README for copyright notice. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. * */ /* This file contains the ieee488 emulator. * The ieee488 emulator calls (modifed) routines from serial.c * to use the standard floppy interface. * The current state of the bus and methods to set output lines * are exported. * This hardware emulation is necessary, as different PET kernels would * need different traps. But it's also much faster than the (hardware * simulated) serial bus, as it's parallel. So we don't need traps. */ #include "vice.h" #include <stdio.h> #include "types.h" #include "parallel.h" #include "serial.h" /* globals */ int pardebug = 0; /* state of the bus lines - if(par_eoi) { eoi is detected } */ char par_eoi = 0; char par_ndac = 0; char par_nrfd = 0; char par_dav = 0; char par_atn = 0; BYTE par_bus = 0; /* data lines */ int par_status = 0; /* lower 8 bits = PET par_status, upper bits own */ /* local values */ /* what has been put on the bus from the CPU - to detect changes */ static char par_eoi_out = 0; static char par_ndac_out = 0; static char par_nrfd_out = 0; static char par_dav_out = 0; static char par_atn_out = 0; static BYTE par_bus_out = 0; /* data lines */ /* what has been put on the bus from the device */ static char par_eoi_dev = 0; static char par_ndac_dev = 0; static char par_nrfd_dev = 0; static char par_dav_dev = 0; static char par_atn_dev = 0; static BYTE par_bus_dev = 0; /* data lines */ /* set the real bus line values by 'wire-oring' the signals */ #define set_atn_out(a) par_atn_out=(a);par_atn=par_atn_dev|par_atn_out #define set_ndac_out(a) par_ndac_out=(a);par_ndac=par_ndac_dev|par_ndac_out #define set_nrfd_out(a) par_nrfd_out=(a);par_nrfd=par_nrfd_dev|par_nrfd_out #define set_dav_out(a) par_dav_out=(a);par_dav=par_dav_dev|par_dav_out #define set_eoi_out(a) par_eoi_out=(a);par_eoi=par_eoi_dev|par_eoi_out #define set_bus_out(a) par_bus_out=(a);par_bus=par_bus_dev|par_bus_out /* set the real bus line values by 'wire-oring' the signals */ #define set_atn_dev(a) par_atn_dev=(a);par_atn=par_atn_dev|par_atn_out #define set_ndac_dev(a) par_ndac_dev=(a);par_ndac=par_ndac_dev|par_ndac_out #define set_nrfd_dev(a) par_nrfd_dev=(a);par_nrfd=par_nrfd_dev|par_nrfd_out #define set_dav_dev(a) par_dav_dev=(a);par_dav=par_dav_dev|par_dav_out #define set_eoi_dev(a) par_eoi_dev=(a);par_eoi=par_eoi_dev|par_eoi_out #define set_bus_dev(a) par_bus_dev=(a);par_bus=par_bus_dev|par_bus_out /*************************************************************************** * State engine for the parallel bus * * Names here are as seen from a device, not from the PET * * Possible States * WaitATN Wait for ATN, ignore everything else * * In1 Wait for DAV low when reading a byte * In2 Wait for DAV high when reading a byte * * OldPet The PET 3032 doesn't set NRFD and NDAC low * before releasing ATN after a TALK command, * wait for a NDAC low first! * * Out1 Wait for NRFD high when sending a byte * Out1a Wait for NRFD low when sending a byte * Trying to save this didn't work * Out2 Wait for NDAC high when sending a byte * * * Each state reacts on the different line transitions. * * atnlo, atnhi, ndaclo, ndachi, nrfdlo, nrfdhi, davlo, davhi * * * Some common functions are: * * ResetBus Set all lines high * ignore ignore any transition * unexpected this transition is unexpected * * Go change the state * * Globals: * * Trans[] name of the transitions * State[] jump table * state actual state */ #define NTRANS 8 /* number of possible transitions */ #define NSTATE 7 /* States */ #define WaitATN 0 #define In1 1 #define In2 2 #define OldPet 3 #define Out1 4 #define Out1a 5 #define Out2 6 /* Transitions */ #define ATNlo 0 #define ATNhi 1 #define DAVlo 2 #define DAVhi 3 #define NDAClo 4 #define NDAChi 5 #define NRFDlo 6 #define NRFDhi 7 typedef struct State_t { char *name; void (*m[NTRANS])(int); } State_t; static char *Trans[NTRANS] = { "ATN low", "ATN high", "DAV low", "DAV high", "NDAC low", "NDAC high", "NRFD low", "NRFD high" }; static State_t State[NSTATE]; static int state = WaitATN; #define Go(a) state=(a);return #define isListening() ((par_status&0xf000)==0x2000) #define isTalking() ((par_status&0xf000)==0x4000) /*#define DoTrans(a) State[state].m[(a)](a)}*/ static void DoTrans(int tr) { State[state].m[tr](tr); fflush(stdout); } static void ResetBus(void) { set_atn_dev(0); set_dav_dev(0); set_eoi_dev(0); set_nrfd_dev(0); set_ndac_dev(0); set_bus_dev(0); par_status = 0; } static void ignore(int i) {} static void unexpected(int trans) { if(pardebug) printf("IEEE488: unexpected line transition in state %s: %s\n", State[state].name, Trans[trans]); } static void WATN_atnlo(int tr) { set_ndac_dev(1); set_dav_dev(0); set_eoi_dev(0); set_bus_dev(0); set_nrfd_dev(0); Go(In1); } #define In1_atnlo WATN_atnlo static void In1_atnhi(int tr) { if(par_status & 0xff) { ResetBus(); Go(WaitATN); } else if(isListening()) { Go(In1); } else if(isTalking()) { ResetBus(); if(!par_ndac) { /* old pet... */ Go(OldPet); } else { State[OldPet].m[NDAClo](tr); return; } } else { if(pardebug) printf("IEEE488: Ouch, something weird happened: %s got %s\n", State[In1].name, Trans[tr]); ResetBus(); Go(WaitATN); } } static void In1_davlo(int tr) { static BYTE b; set_nrfd_dev(1); b = par_bus; set_ndac_dev(0); if(par_atn) { par_status = parallelattention(b); } else { par_status = parallelsendbyte(b); } if(pardebug) printf("IEEE488: sendbyte returns %04x\n",par_status); Go(In2); } static void In1_ndaclo(int tr) { if(!par_atn) unexpected(tr); } static void In1_nrfdlo(int tr) { if(!par_atn) unexpected(tr); } static void In1_nrfdhi(int tr) { unexpected(tr); } #define In2_atnlo WATN_atnlo static void In2_atnhi(a) { /* atn data transfer interrupted */ ResetBus(); Go(WaitATN); /* ??? */ } static void In2_davhi(int tr) { set_ndac_dev(1); set_nrfd_dev(0); Go(In1); } #define OPet_atnlo WATN_atnlo static void OPet_ndaclo(int tr) { if(!par_nrfd) { State[Out1].m[NRFDhi](tr); return; } else { Go(Out1); } } #define Out1_atnlo WATN_atnlo static void Out1_nrfdhi(int tr) { static BYTE b; par_status = parallelreceivebyte(&b, 1); /*if(par_status & 0xff) printf("IEEE488: Out1_nrfdhi: par_status=%x\n",par_status);*/ if(par_status & 0x40) { set_eoi_dev(1); } else { set_eoi_dev(0); } set_bus_dev(b^255); set_dav_dev(1); Go(Out1a); } #define Out1a_atnlo WATN_atnlo static void Out1a_nrfdlo(int tr) { Go(Out2); } static void Out1a_ndachi(int tr) { ResetBus(); Go(WaitATN); } #define Out2_atnlo WATN_atnlo static void Out2_ndachi(int tr) { static BYTE b; set_dav_dev(0); set_eoi_dev(0); set_bus_dev(0); par_status = parallelreceivebyte(&b, 0); /*if(par_status & 0xff) printf("IEEE488: Out2_ndachi: par_status=%x\n",par_status);*/ if(par_status & 0xff) { ResetBus(); Go(WaitATN); } else { Go(Out1); } } /************************************************************************** * State table * */ static State_t State[NSTATE] = { { "WaitATN", { WATN_atnlo, ignore, ignore, ignore, ignore, ignore, ignore, ignore } }, { "In1", { In1_atnlo, In1_atnhi, In1_davlo, unexpected, In1_ndaclo, unexpected, In1_nrfdlo, In1_nrfdhi } }, { "In2", { In2_atnlo, In2_atnhi, unexpected, In2_davhi, unexpected, unexpected, unexpected, unexpected } }, { "OldPet", { OPet_atnlo, unexpected, unexpected, unexpected, OPet_ndaclo, unexpected, unexpected, unexpected } }, { "Out1", { Out1_atnlo, unexpected, unexpected, unexpected, ignore, unexpected, unexpected, Out1_nrfdhi } }, { "Out1a", { Out1a_atnlo, unexpected, unexpected, unexpected, unexpected, Out1a_ndachi, Out1a_nrfdlo, unexpected } }, { "Out2", { Out2_atnlo, unexpected, unexpected, unexpected, unexpected, Out2_ndachi, unexpected, unexpected } } }; /************************************************************************** * methods to set output lines for the CPU * */ void par_set_atn( char b ) { if(b==par_atn_out) return; set_atn_out(b); if(pardebug) printf("par_set_atn(%d)\n",b); if(b) DoTrans(ATNlo); else DoTrans(ATNhi); return; } void par_set_ndac( char b ) { if(b==par_ndac_out) return; set_ndac_out(b); if(b) DoTrans(NDAClo); else DoTrans(NDAChi); return; } void par_set_nrfd( char b ) { if(b==par_nrfd_out) return; set_nrfd_out(b); if(b) DoTrans(NRFDlo); else DoTrans(NRFDhi); return; } void par_set_dav( char b ) { if(b==par_dav_out) return; set_dav_out(b); if(b) DoTrans(DAVlo); else DoTrans(DAVhi); return; } void par_set_bus( BYTE b ) { if(b==par_bus_out) return; set_bus_out(b); if(pardebug) printf("par_set_bus(%d)\n",b); } void par_set_eoi( char b ) { if(b==par_eoi_out) return; set_eoi_out(b); if(pardebug) printf("par_set_eoi(%d)\n",b); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.