Sym53C810.cpp

Go to the documentation of this file.
00001 /* ES40 emulator.
00002  * Copyright (C) 2007-2008 by the ES40 Emulator Project
00003  *
00004  * WWW    : http://sourceforge.net/projects/es40
00005  * E-mail : camiel@camicom.com
00006  * 
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00020  * 
00021  * Although this is not required, the author would appreciate being notified of, 
00022  * and receiving any modifications you may make to the source code that might serve
00023  * the general public.
00024  */
00025 
00067 #if defined(DEBUG_SYM)
00068 #define DEBUG_SYM_REGS
00069 #define DEBUG_SYM_SCRIPTS
00070 #endif
00071 #include "StdAfx.h"
00072 #include "Sym53C810.h"
00073 #include "System.h"
00074 #include "Disk.h"
00075 #include "SCSIBus.h"
00076 
00078 #define R_SCNTL0        0x00
00079 #define R_SCNTL0_ARB1   0x80
00080 #define R_SCNTL0_ARB0   0x40
00081 #define R_SCNTL0_START  0x20
00082 #define R_SCNTL0_WATN   0x10
00083 #define R_SCNTL0_EPC    0x08
00084 #define R_SCNTL0_AAP    0x02
00085 #define R_SCNTL0_TRG    0x01
00086 #define SCNTL0_MASK     0xFB
00087 
00089 #define R_SCNTL1        0x01
00090 #define R_SCNTL1_CON    0x10
00091 #define R_SCNTL1_RST    0x08
00092 #define R_SCNTL1_IARB   0x02
00093 
00095 #define R_SCNTL2        0x02
00096 #define R_SCNTL2_SDU    0x80
00097 #define SCNTL2_MASK     0x80
00098 
00100 #define R_SCNTL3        0x03
00101 #define SCNTL3_MASK     0x77
00102 
00104 #define R_SCID          0x04
00105 #define R_SCID_ID       0x07
00106 #define SCID_MASK       0x67
00107 
00109 #define R_SXFER         0x05
00110 
00112 #define R_SDID          0x06
00113 #define R_SDID_ID       0x07
00114 #define SDID_MASK       0x07
00115 
00117 #define R_GPREG         0x07
00118 #define GPREG_MASK      0x03
00119 
00121 #define R_SFBR          0x08
00122 
00124 #define R_SOCL          0x09
00125 #define R_SOCL_ACK      0x40
00126 #define R_SOCL_ATN      0x20
00127 
00129 #define R_SSID          0x0A
00130 #define R_SSID_VAL      0x80
00131 #define R_SSID_ID       0x07
00132 
00134 #define R_SBCL          0x0B
00135 #define R_SBCL_REQ      0x80
00136 #define R_SBCL_ACK      0x40
00137 #define R_SBCL_BSY      0x20
00138 #define R_SBCL_SEL      0x10
00139 #define R_SBCL_ATN      0x08
00140 #define R_SBCL_MSG      0x04
00141 #define R_SBCL_CD       0x02
00142 #define R_SBCL_IO       0x01
00143 #define R_SBCL_PHASE    0x07
00144 
00146 #define R_DSTAT         0x0C
00147 #define R_DSTAT_DFE     0x80
00148 #define R_DSTAT_MDPE    0x40
00149 #define R_DSTAT_BF      0x20
00150 #define R_DSTAT_ABRT    0x10
00151 #define R_DSTAT_SSI     0x08
00152 #define R_DSTAT_SIR     0x04
00153 #define R_DSTAT_IID     0x01
00154 #define DSTAT_RC        0x7D
00155 #define DSTAT_FATAL     0x7D
00156 
00158 #define R_SSTAT0        0x0D
00159 #define R_SSTAT0_RST    0x02
00160 #define R_SSTAT0_SDP0   0x01
00161 
00163 #define R_SSTAT1        0x0E
00164 #define R_SSTAT1_SDP1   0x01
00165 
00167 #define R_SSTAT2        0x0F
00168 #define R_SSTAT2_LDSC   0x02
00169 
00171 #define R_DSA           0x10
00172 
00174 #define R_ISTAT         0x14
00175 #define R_ISTAT_ABRT    0x80
00176 #define R_ISTAT_SRST    0x40
00177 #define R_ISTAT_SIGP    0x20
00178 #define R_ISTAT_SEM     0x10
00179 #define R_ISTAT_CON     0x08
00180 #define R_ISTAT_INTF    0x04
00181 #define R_ISTAT_SIP     0x02
00182 #define R_ISTAT_DIP     0x01
00183 #define ISTAT_MASK      0xF0
00184 #define ISTAT_W1C       0x04
00185 
00187 #define R_CTEST0        0x18
00188 
00190 #define R_CTEST1        0x19
00191 #define R_CTEST1_FMT    0xF0
00192 #define R_CTEST1_FFL    0x0F
00193 
00195 #define R_CTEST2        0x1A
00196 #define R_CTEST2_DDIR   0x80
00197 #define R_CTEST2_SIGP   0x40
00198 #define R_CTEST2_CIO    0x20
00199 #define R_CTEST2_CM     0x10
00200 #define R_CTEST2_TEOP   0x04
00201 #define R_CTEST2_DREQ   0x02
00202 #define R_CTEST2_DACK   0x01
00203 
00205 #define R_CTEST3        0x1B
00206 #define R_CTEST3_REV    0xf0
00207 #define R_CTEST3_FLF    0x08
00208 #define R_CTEST3_CLF    0x04
00209 #define R_CTEST3_FM     0x02
00210 #define CTEST3_MASK     0x0B
00211 
00213 #define R_TEMP          0x1C
00214 
00216 #define R_DFIFO         0x20
00217 
00219 #define R_CTEST4        0x21
00220 
00222 #define R_CTEST5        0x22
00223 #define R_CTEST5_ADCK   0x80
00224 #define R_CTEST5_BBCK   0x40
00225 #define CTEST5_MASK     0x18
00226 
00228 #define R_DBC           0x24
00229 
00231 #define R_DCMD          0x27
00232 
00234 #define R_DNAD          0x28
00235 
00237 #define R_DSP           0x2C
00238 
00240 #define R_DSPS          0x30
00241 
00243 #define R_SCRATCHA      0x34
00244 
00246 #define R_DMODE         0x38
00247 #define R_DMODE_MAN     0x01
00248 
00250 #define R_DIEN          0x39
00251 #define DIEN_MASK       0x7D
00252 
00254 #define R_SBR           0x3A
00255 
00257 #define R_DCNTL         0x3B
00258 #define R_DCNTL_SSM     0x10
00259 #define R_DCNTL_STD     0x04
00260 #define R_DCNTL_IRQD    0x02
00261 #define R_DCNTL_COM     0x01
00262 #define DCNTL_MASK      0xFB
00263 
00265 #define R_ADDER         0x3C
00266 
00268 #define R_SIEN0         0x40
00269 #define SIEN0_MASK      0xFF
00270 
00272 #define R_SIEN1         0x41
00273 #define SIEN1_MASK      0x07
00274 
00276 #define R_SIST0         0x42
00277 #define R_SIST0_MA      0x80
00278 #define R_SIST0_CMP     0x40
00279 #define R_SIST0_SEL     0x20
00280 #define R_SIST0_RSL     0x10
00281 #define R_SIST0_SGE     0x08
00282 #define R_SIST0_UDC     0x04
00283 #define R_SIST0_RST     0x02
00284 #define R_SIST0_PAR     0x01
00285 #define SIST0_RC        0xFF
00286 #define SIST0_FATAL     0x8F
00287 
00289 #define R_SIST1         0x43
00290 #define R_SIST1_STO     0x04
00291 #define R_SIST1_GEN     0x02
00292 #define R_SIST1_HTH     0x01
00293 #define SIST1_RC        0x07
00294 #define SIST1_FATAL     0x04
00295 
00297 #define R_MACNTL        0x46
00298 #define MACNTL_MASK     0x0F
00299 
00301 #define R_GPCNTL        0x47
00302 
00304 #define R_STIME0        0x48
00305 
00307 #define R_STIME1        0x49
00308 #define R_STIME1_GEN    0x0F
00309 #define STIME1_MASK     0x0F
00310 
00312 #define R_RESPID        0x4A
00313 
00315 #define R_STEST0        0x4C
00316 
00318 #define R_STEST1        0x4D
00319 #define STEST1_MASK     0xC0
00320 
00322 #define R_STEST2        0x4E
00323 #define R_STEST2_SCE    0x80
00324 #define R_STEST2_ROF    0x40
00325 #define R_STEST2_SLB    0x10
00326 #define R_STEST2_SZM    0x08
00327 #define R_STEST2_EXT    0x02
00328 #define R_STEST2_LOW    0x01
00329 #define STEST2_MASK     0x9B
00330 
00332 #define R_STEST3        0x4F
00333 #define R_STEST3_TE     0x80
00334 #define R_STEST3_STR    0x40
00335 #define R_STEST3_HSC    0x20
00336 #define R_STEST3_DSI    0x10
00337 #define R_STEST3_TTM    0x04
00338 #define R_STEST3_CSF    0x02
00339 #define R_STEST3_STW    0x01
00340 #define STEST3_MASK     0xF7
00341 
00343 #define R_SBDL          0x58
00344 
00346 #define R_SCRATCHB      0x5C
00347 
00349 #define R8(a)           state.regs.reg8[R_##a]
00350 
00352 #define R16(a)          state.regs.reg16[R_##a / 2]
00353 
00355 #define R32(a)          state.regs.reg32[R_##a / 4]
00356 
00363 #define TB_R8(a, b) ((R8(a) & R_##a##_##b) == R_##a##_##b)
00364 
00372 #define SB_R8(a, b, c)  R8(a) = (R8(a) &~R_##a##_##b) | (c ? R_##a##_##b : 0)
00373 
00382 #define WRM_R8(a, b)  R8(a) = (R8(a) &~a##_MASK) | ((b) & a##_MASK)
00383 
00394 #define WRMW1C_R8(a, b)                    \
00395     R8(a) = (R8(a) &~a##_MASK &~a##_W1C) | \
00396     ((b) & a##_MASK) |                     \
00397     (R8(a) &~(b) & a##_W1C)
00398 
00405 #define RAISE(a, b) set_interrupt(R_##a, R_##a##_##b)
00406 
00414 #define RDCLR_R8(a) R8(a) &= ~a##_RC
00415 
00419 #define GET_DEST()  (R8(SDID) & R_SCID_ID)
00420 
00424 #define SET_DEST(a) R8(SDID) = (a) & R_SCID_ID
00425 
00429 #define GET_DBC()   (R32(DBC) & 0x00ffffff)
00430 
00434 #define SET_DBC(a)                       \
00435     R32(DBC) = (R32(DBC) & 0xff000000) | \
00436     ((a) & 0x00ffffff)
00437 
00441 static u32 osym_cfg_data[64] =
00442 {
00443   /*00*/  0x00011000,         // CFID: vendor + device
00444   /*04*/  0x02000001,         // CFCS: command + status
00445   /*08*/  0x01000001,         // CFRV: class + revision
00446   /*0c*/  0x00000000,         // CFLT: latency timer + cache line size
00447   /*10*/  0x00000001,         // BAR0: IO Space
00448   /*14*/  0x00000000,         // BAR1: Memory space
00449   /*18*/  0x00000000,         // BAR2: RAM space
00450   /*1c*/  0x00000000,         // BAR3:
00451   /*20*/  0x00000000,         // BAR4:
00452   /*24*/  0x00000000,         // BAR5:
00453   /*28*/  0x00000000,         // CCIC: CardBus
00454   /*2c*/  0x00000000,         // CSID: subsystem + vendor
00455   /*30*/  0x00000000,         // BAR6: expansion rom base
00456   /*34*/  0x00000000,         // CCAP: capabilities pointer
00457   /*38*/  0x00000000,
00458   /*3c*/  0x401101ff,         // CFIT: interrupt configuration
00459   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00460   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00461   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00462 };
00463 
00467 static u32 osym_cfg_mask[64] = {
00468   /*00*/ 0x00000000,  // CFID: vendor + device
00469   /*04*/ 0x00000157,  // CFCS: command + status
00470   /*08*/ 0x00000000,  // CFRV: class + revision
00471   /*0c*/ 0x0000ffff,  // CFLT: latency timer + cache line size
00472   /*10*/ 0xffffff00,  // BAR0: IO space (256 bytes)
00473   /*14*/ 0xffffff00,  // BAR1: Memory space (256 bytes)
00474   /*18*/ 0x00000000,  // BAR2: RAM space (4KB)
00475   /*1c*/ 0x00000000,  // BAR3:
00476   /*20*/ 0x00000000,  // BAR4:
00477   /*24*/ 0x00000000,  // BAR5:
00478   /*28*/ 0x00000000,  // CCIC: CardBus
00479   /*2c*/ 0x00000000,  // CSID: subsystem + vendor
00480   /*30*/ 0x00000000,  // BAR6: expansion rom base
00481   /*34*/ 0x00000000,  // CCAP: capabilities pointer
00482   /*38*/ 0x00000000,
00483   /*3c*/ 0x000000ff,  // CFIT: interrupt configuration
00484   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00485   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00486   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00487 };
00488 
00497 void CSym53C810::run()
00498 {
00499   try
00500   {
00501     for(;;)
00502     {
00503       mySemaphore.wait();
00504       if(StopThread)
00505         return;
00506       while(state.executing)
00507       {
00508         MUTEX_LOCK(myRegLock);
00509         execute();
00510         MUTEX_UNLOCK(myRegLock);
00511       }
00512     }
00513   }
00514 
00515   catch(Poco::Exception & e)
00516   {
00517     printf("Exception in SYM thread: %s.\n", e.displayText().c_str());
00518 
00519     // Let the thread die...
00520   }
00521 }
00522 
00529 CSym53C810::CSym53C810(CConfigurator* cfg, CSystem* c, int pcibus, int pcidev) : CDiskController(cfg, c, pcibus, pcidev, 1, 7), mySemaphore(0, 1)
00530 {
00531 
00532   // create scsi bus
00533   CSCSIBus*   a = new CSCSIBus(cfg, c);
00534   scsi_register(0, a, 7); // scsi id 7 by default
00535 }
00536 
00542 void CSym53C810::init()
00543 {
00544   add_function(0, osym_cfg_data, osym_cfg_mask);
00545 
00546   ResetPCI();
00547 
00548   chip_reset();
00549 
00550   myRegLock = new CMutex("sym-reg");
00551 
00552   myThread = 0;
00553 
00554   printf("%s: $Id: Sym53C810.cpp,v 1.12 2008/03/25 20:46:20 iamcamiel Exp $\n",
00555          devid_string);
00556 }
00557 
00561 void CSym53C810::start_threads()
00562 {
00563   if(!myThread)
00564   {
00565     myThread = new Poco::Thread("sym");
00566     printf(" %s", myThread->getName().c_str());
00567     StopThread = false;
00568     myThread->start(*this);
00569     if(state.executing)
00570       mySemaphore.set();
00571   }
00572 }
00573 
00577 void CSym53C810::stop_threads()
00578 {
00579   StopThread = true;
00580   if(myThread)
00581   {
00582     printf(" %s", myThread->getName().c_str());
00583     mySemaphore.set();
00584     myThread->join();
00585     delete myThread;
00586     myThread = 0;
00587   }
00588 }
00589 
00595 CSym53C810::~CSym53C810()
00596 {
00597   stop_threads();
00598   delete scsi_bus[0];
00599 }
00600 
00606 void CSym53C810::chip_reset()
00607 {
00608   state.executing = false;
00609   state.wait_reselect = false;
00610   state.irq_asserted = false;
00611   state.gen_timer = 0;
00612   memset(state.regs.reg32, 0, sizeof(state.regs.reg32));
00613   R8(SCNTL0) = R_SCNTL0_ARB1 | R_SCNTL0_ARB0; // 810
00614   R8(DSTAT) = R_DSTAT_DFE;    // DMA FIFO empty // 810
00615 
00616   //  R8(SSTAT2) = R_SSTAT2_LDSC; // 810
00617   R8(CTEST1) = R_CTEST1_FMT;  // 810
00618   R8(CTEST2) = R_CTEST2_DACK; // 810
00619   R8(CTEST3) = (u8) (pci_state.config_data[0][2] << 4) & R_CTEST3_REV;  // Chip rev.
00620   R8(MACNTL) = 0x40;  // 810 type ID
00621   R8(GPCNTL) = 0x0F;  // 810
00622   R8(STEST0) = 0x03;  // 810
00623 }
00624 
00630 void CSym53C810::register_disk(class CDisk* dsk, int bus, int dev)
00631 {
00632   CDiskController::register_disk(dsk, bus, dev);
00633   dsk->scsi_register(0, scsi_bus[0], dev);
00634 }
00635 
00636 static u32  sym_magic1 = 0x53C810CC;
00637 static u32  sym_magic2 = 0xCC53C810;
00638 
00642 int CSym53C810::SaveState(FILE* f)
00643 {
00644   long  ss = sizeof(state);
00645   int   res;
00646 
00647   if(res = CPCIDevice::SaveState(f))
00648     return res;
00649 
00650   fwrite(&sym_magic1, sizeof(u32), 1, f);
00651   fwrite(&ss, sizeof(long), 1, f);
00652   fwrite(&state, sizeof(state), 1, f);
00653   fwrite(&sym_magic2, sizeof(u32), 1, f);
00654   printf("%s: %d bytes saved.\n", devid_string, (int) ss);
00655   return 0;
00656 }
00657 
00661 int CSym53C810::RestoreState(FILE* f)
00662 {
00663   long    ss;
00664   u32     m1;
00665   u32     m2;
00666   int     res;
00667   size_t  r;
00668 
00669   if(res = CPCIDevice::RestoreState(f))
00670     return res;
00671 
00672   r = fread(&m1, sizeof(u32), 1, f);
00673   if(r != 1)
00674   {
00675     printf("%s: unexpected end of file!\n", devid_string);
00676     return -1;
00677   }
00678 
00679   if(m1 != sym_magic1)
00680   {
00681     printf("%s: MAGIC 1 does not match!\n", devid_string);
00682     return -1;
00683   }
00684 
00685   fread(&ss, sizeof(long), 1, f);
00686   if(r != 1)
00687   {
00688     printf("%s: unexpected end of file!\n", devid_string);
00689     return -1;
00690   }
00691 
00692   if(ss != sizeof(state))
00693   {
00694     printf("%s: STRUCT SIZE does not match!\n", devid_string);
00695     return -1;
00696   }
00697 
00698   fread(&state, sizeof(state), 1, f);
00699   if(r != 1)
00700   {
00701     printf("%s: unexpected end of file!\n", devid_string);
00702     return -1;
00703   }
00704 
00705   r = fread(&m2, sizeof(u32), 1, f);
00706   if(r != 1)
00707   {
00708     printf("%s: unexpected end of file!\n", devid_string);
00709     return -1;
00710   }
00711 
00712   if(m2 != sym_magic2)
00713   {
00714     printf("%s: MAGIC 1 does not match!\n", devid_string);
00715     return -1;
00716   }
00717 
00718   printf("%s: %d bytes restored.\n", devid_string, (int) ss);
00719   return 0;
00720 }
00721 
00725 void CSym53C810::WriteMem_Bar(int func, int bar, u32 address, int dsize, u32 data)
00726 {
00727   void*   p;
00728 
00729   switch(bar)
00730   {
00731   case 0:
00732   case 1:
00733     address &= 0x7f;
00734     switch(dsize)
00735     {
00736     case 8:
00737       MUTEX_LOCK(myRegLock);
00738 #if defined(DEBUG_SYM_REGS)
00739       printf("SYM: Write to register %02x: %02x.   \n", address, data);
00740 #endif
00741       if(address >= R_SCRATCHB)
00742       {
00743         state.regs.reg8[address] = (u8) data;
00744         MUTEX_UNLOCK(myRegLock);
00745         break;
00746       }
00747 
00748       switch(address)
00749       {
00750 
00751       // SIMPLE CASES: JUST WRITE
00752       case R_SXFER:             // 05
00753       case R_DSA:               // 10
00754       case R_DSA + 1:           // 11
00755       case R_DSA + 2:           // 12
00756       case R_DSA + 3:           // 13
00757       case R_CTEST0:            // 18
00758       case R_TEMP:              // 1C
00759       case R_TEMP + 1:          // 1D
00760       case R_TEMP + 2:          // 1E
00761       case R_TEMP + 3:          // 1F
00762       case R_DSP:               // 2C
00763       case R_DSP + 1:           // 2D
00764       case R_DSP + 2:           // 2E
00765       case R_DSPS:              // 30
00766       case R_DSPS + 1:          // 31
00767       case R_DSPS + 2:          // 32
00768       case R_DSPS + 3:          // 33
00769       case R_SCRATCHA:          // 34
00770       case R_SCRATCHA + 1:      // 35
00771       case R_SCRATCHA + 2:      // 36
00772       case R_SCRATCHA + 3:      // 37
00773       case R_DMODE:             // 38
00774       case R_SBR:               // 3A     // 810
00775       case R_GPCNTL:            // 47
00776       case R_STIME0:            // 48
00777       case R_RESPID:            // 4A
00778       case R_STEST0:            // 4C
00779         state.regs.reg8[address] = (u8) data;
00780         break;
00781 
00782       case R_SCNTL0:            // 00
00783         // side effects: start arbitration bit
00784         write_b_scntl0((u8) data);
00785         break;
00786 
00787       case R_SCNTL1:            //01
00788         // side effects: start immediate arbitration bit
00789         write_b_scntl1((u8) data);
00790         break;
00791 
00792       case R_SCNTL2:            //02
00793         WRM_R8(SCNTL2, (u8) data);
00794         break;
00795 
00796       case R_SCNTL3:            //03
00797         // side effects: clearing EWS
00798         WRM_R8(SCNTL3, (u8) data);
00799         break;
00800 
00801       case R_SCID:              // 04
00802         WRM_R8(SCID, (u8) data);
00803         break;
00804 
00805       case R_SDID:              // 06
00806         WRM_R8(SDID, (u8) data);
00807         break;
00808 
00809       case R_GPREG:             // 07
00810         WRM_R8(GPREG, (u8) data);
00811         break;
00812 
00813       case R_ISTAT:             // 14
00814         write_b_istat((u8) data);
00815         break;
00816 
00817       case R_CTEST3:            // 1B
00818         write_b_ctest3((u8) data);
00819         break;
00820 
00821       case R_CTEST4:            // 21
00822         write_b_ctest4((u8) data);
00823         break;
00824 
00825       case R_CTEST5:            // 22
00826         write_b_ctest5((u8) data);
00827         break;
00828 
00829       case R_DSP + 3:           // 2F
00830         state.regs.reg8[address] = (u8) data;
00831         post_dsp_write();
00832         break;
00833 
00834       case R_DIEN:              // 39
00835         WRM_R8(DIEN, (u8) data);
00836         eval_interrupts();
00837         break;
00838 
00839       case R_DCNTL:             // 3B
00840         write_b_dcntl((u8) data);
00841         break;
00842 
00843       case R_SIEN0:             // 40
00844         R8(SIEN0) = (u8) data;
00845         eval_interrupts();
00846         break;
00847 
00848       case R_SIEN1:             // 41
00849         WRM_R8(SIEN1, (u8) data);
00850         eval_interrupts();
00851         break;
00852 
00853       case R_MACNTL:            // 46     // 810
00854         WRM_R8(MACNTL, (u8) data);
00855         break;
00856 
00857       case R_STIME1:            // 49
00858         WRM_R8(STIME1, (u8) data);
00859         state.gen_timer = (R8(STIME1) & R_STIME1_GEN) * 30;
00860         break;
00861 
00862       case R_STEST1:            // 4D
00863         WRM_R8(STEST1, (u8) data);
00864         break;
00865 
00866       case R_STEST2:            // 4E
00867         write_b_stest2((u8) data);
00868         break;
00869 
00870       case R_STEST3:            // 4F
00871         write_b_stest3((u8) data);
00872         break;
00873 
00874       case R_DSTAT:             // 0C
00875       case R_SSTAT0:            // 0D
00876       case R_SSTAT1:            // 0E
00877       case R_SSTAT2:            // 0F
00878       case R_CTEST2:            // 1A
00879         //printf("SYM: Write to read-only register at %02x. FreeBSD driver cache test.\n", address);
00880         break;
00881 
00882       case 0x4b:                // ??? Linux wants this
00883         //printf("SYM: Write to non-existing register at %02x. Linux generic driver.\n", address);
00884         break;
00885 
00886       default:
00887         FAILURE_2(NotImplemented,
00888                   "SYM: Write to unknown register at %02x with %08x.\n", address,
00889                   data);
00890       }
00891 
00892       MUTEX_UNLOCK(myRegLock);
00893       break;
00894 
00895     case 16:
00896       WriteMem_Bar(0, 1, address + 0, 8, (data >> 0) & 0xff);
00897       WriteMem_Bar(0, 1, address + 1, 8, (data >> 8) & 0xff);
00898       break;
00899 
00900     case 32:
00901       WriteMem_Bar(0, 1, address + 0, 8, (data >> 0) & 0xff);
00902       WriteMem_Bar(0, 1, address + 1, 8, (data >> 8) & 0xff);
00903       WriteMem_Bar(0, 1, address + 2, 8, (data >> 16) & 0xff);
00904       WriteMem_Bar(0, 1, address + 3, 8, (data >> 24) & 0xff);
00905       break;
00906     }
00907     break;
00908 
00909   case 2:
00910     p = (u8*) state.ram + address;
00911     switch(dsize)
00912     {
00913     case 8:   *((u8*) p) = (u8) data; break;
00914     case 16:  *((u16*) p) = (u16) data; break;
00915     case 32:  *((u32*) p) = (u32) data; break;
00916     }
00917     break;
00918   }
00919 }
00920 
00924 u32 CSym53C810::ReadMem_Bar(int func, int bar, u32 address, int dsize)
00925 {
00926   u32     data = 0;
00927   void*   p;
00928 
00929   switch(bar)
00930   {
00931   case 0:
00932   case 1:
00933     address &= 0x7f;
00934     switch(dsize)
00935     {
00936     case 8:
00937       MUTEX_LOCK(myRegLock);
00938       if(address >= R_SCRATCHB)
00939       {
00940         data = state.regs.reg8[address];
00941         MUTEX_UNLOCK(myRegLock);
00942         break;
00943       }
00944 
00945       switch(address)
00946       {
00947       case R_SCNTL0:            // 00
00948       case R_SCNTL1:            // 01
00949       case R_SCNTL2:            // 02
00950       case R_SCNTL3:            // 03
00951       case R_SCID:              // 04
00952       case R_SXFER:             // 05
00953       case R_SDID:              // 06
00954       case R_GPREG:             // 07
00955       case R_SFBR:              // 08
00956       case R_SSID:              // 0A
00957       case R_SBCL:              // 0B
00958       case R_SSTAT0:            // 0D
00959       case R_SSTAT1:            // 0E
00960       case R_SSTAT2:            // 0F
00961       case R_DSA:               // 10
00962       case R_DSA + 1:           // 11
00963       case R_DSA + 2:           // 12
00964       case R_DSA + 3:           // 13
00965       case R_ISTAT:             // 14
00966       case R_CTEST0:            // 18
00967       case R_CTEST1:            // 19
00968       case R_CTEST3:            // 1B
00969       case R_TEMP:              // 1C
00970       case R_TEMP + 1:          // 1D
00971       case R_TEMP + 2:          // 1E
00972       case R_TEMP + 3:          // 1F
00973       case R_CTEST4:            // 21
00974       case R_CTEST5:            // 22
00975       case R_DBC:               // 24  // 810
00976       case R_DBC + 1:           // 25  // 810
00977       case R_DBC + 2:           // 26  // 810
00978       case R_DCMD:              // 27  // 810
00979       case R_DNAD:              // 28  // 810
00980       case R_DNAD + 1:          // 29  // 810
00981       case R_DNAD + 2:          // 2A  // 810
00982       case R_DNAD + 3:          // 2B  // 810
00983       case R_DSP:               // 2C
00984       case R_DSP + 1:           // 2D
00985       case R_DSP + 2:           // 2E
00986       case R_DSP + 3:           // 2F
00987       case R_DSPS:              // 30
00988       case R_DSPS + 1:          // 31
00989       case R_DSPS + 2:          // 32
00990       case R_DSPS + 3:          // 33
00991       case R_SCRATCHA:          // 34
00992       case R_SCRATCHA + 1:      // 35
00993       case R_SCRATCHA + 2:      // 36
00994       case R_SCRATCHA + 3:      // 37
00995       case R_DMODE:             // 38
00996       case R_DIEN:              // 39
00997       case R_SBR:               // 3A     // 810
00998       case R_DCNTL:             // 3B
00999       case R_SIEN0:             // 40
01000       case R_SIEN1:             // 41
01001       case R_MACNTL:            // 46     // 810
01002       case R_GPCNTL:            // 47
01003       case R_STIME0:            // 48
01004       case R_STIME1:            // 49
01005       case R_RESPID:            // 4A
01006       case R_STEST0:            // 4C
01007       case R_STEST1:            // 4D
01008       case R_STEST2:            // 4E
01009       case R_STEST3:            // 4F
01010       case R_SBDL:              // 58
01011         data = state.regs.reg8[address];
01012         break;
01013 
01014       case R_DSTAT:             // 0C
01015         data = read_b_dstat();
01016         break;
01017 
01018       case R_CTEST2:            // 1A
01019         data = read_b_ctest2();
01020         break;
01021 
01022       case R_DFIFO:             // 20
01023         data = R8(DBC) & 0x7f;  // 810 - fake the DFIFO count
01024         break;
01025 
01026       case R_SIST0: // 42
01027       case R_SIST1: // 43
01028         data = read_b_sist(address - R_SIST0);
01029         break;
01030 
01031       case 0x17:    // ??? Linux wants this.
01032       case 0x4b:    // ??? Linux wants this
01033       case 0x52:    // ??? Linux wants this.
01034       case 0x59:    // ??? Linux wants this.
01035         //printf("SYM: Read from non-existing register at %02x. Linux generic driver.\n", address);
01036         data = 0;
01037         break;
01038 
01039       default:
01040         FAILURE_2(NotImplemented,
01041                   "SYM: Attempt to read from unknown register at %02x\n", dsize,
01042                   address);
01043       }
01044 
01045       MUTEX_UNLOCK(myRegLock);
01046 #if defined(DEBUG_SYM_REGS)
01047       printf("SYM: Read frm register %02x: %02x.   \n", address, data);
01048 #endif
01049       break;
01050 
01051     case 16:
01052       data = (ReadMem_Bar(0, 1, address + 0, 8) << 0) & 0x00ff;
01053       data |= (ReadMem_Bar(0, 1, address + 1, 8) << 8) & 0xff00;
01054       break;
01055 
01056     case 32:
01057       data = (ReadMem_Bar(0, 1, address + 0, 8) << 0) & 0x000000ff;
01058       data |= (ReadMem_Bar(0, 1, address + 1, 8) << 8) & 0x0000ff00;
01059       data |= (ReadMem_Bar(0, 1, address + 2, 8) << 16) & 0x00ff0000;
01060       data |= (ReadMem_Bar(0, 1, address + 3, 8) << 24) & 0xff000000;
01061       break;
01062     }
01063     break;
01064 
01065   case 2:
01066     p = (u8*) state.ram + address;
01067     switch(dsize)
01068     {
01069     case 8:   return *((u8*) p);
01070     case 16:  return *((u16*) p);
01071     case 32:  return *((u32*) p);
01072     }
01073     break;
01074   }
01075 
01076   return data;
01077 }
01078 
01085 u32 CSym53C810::config_read_custom(int func, u32 address, int dsize, u32 data)
01086 {
01087   if(address >= 0x80)
01088     return ReadMem_Bar(func, 1, address - 0x80, dsize);
01089   else
01090     return data;
01091 }
01092 
01099 void CSym53C810::config_write_custom(int func, u32 address, int dsize,
01100                                      u32 old_data, u32 new_data, u32 data)
01101 {
01102   if(address >= 0x80)
01103     WriteMem_Bar(func, 1, address - 0x80, dsize, data);
01104 }
01105 
01121 void CSym53C810::write_b_scntl0(u8 value)
01122 {
01123   bool  old_start = TB_R8(SCNTL0, START);
01124 
01125   WRM_R8(SCNTL0, value);
01126 
01127   if(TB_R8(SCNTL0, START) && !old_start)
01128     FAILURE(NotImplemented, "SYM: Don't know how to start arbitration sequence");
01129 
01130   if(TB_R8(SCNTL0, TRG))
01131     FAILURE(NotImplemented, "SYM: Don't know how to operate in target mode");
01132 }
01133 
01150 void CSym53C810::write_b_scntl1(u8 value)
01151 {
01152   bool  old_iarb = TB_R8(SCNTL1, IARB);
01153   bool  old_con = TB_R8(SCNTL1, CON);
01154   bool  old_rst = TB_R8(SCNTL1, RST);
01155 
01156   R8(SCNTL1) = value;
01157 
01158   //  if (TB_R8(SCNTL1,CON) != old_con)
01159   //    printf("SYM: Don't know how to forcibly connect or disconnect\n");
01160   if(TB_R8(SCNTL1, RST) != old_rst)
01161   {
01162     SB_R8(SSTAT0, SDP0, false);
01163     SB_R8(SSTAT1, SDP1, false);
01164     R16(SBDL) = 0;
01165     R8(SBCL) = 0;
01166 
01167     SB_R8(SSTAT0, RST, !old_rst);
01168 
01169     //    printf("SYM: %s SCSI bus reset.\n",old_rst?"end":"start");
01170     if(!old_rst)
01171       RAISE(SIST0, RST);
01172   }
01173 
01174 }
01175 
01192 void CSym53C810::write_b_istat(u8 value)
01193 {
01194   bool  old_srst = TB_R8(ISTAT, SRST);
01195   bool  old_sem = TB_R8(ISTAT, SEM);
01196   bool  old_sigp = TB_R8(ISTAT, SIGP);
01197 
01198   WRMW1C_R8(ISTAT, value);
01199 
01200   if(TB_R8(ISTAT, ABRT))
01201   {
01202 
01203     //    printf("SYM: Aborting on request.\n");
01204     RAISE(DSTAT, ABRT);
01205   }
01206 
01207   if(TB_R8(ISTAT, SRST) && !old_srst)
01208   {
01209 
01210     //    printf("SYM: Resetting on request.\n");
01211     chip_reset();
01212   }
01213 
01214   //  if (TB_R8(ISTAT,SEM) != old_sem)
01215   //    printf("SYM: SEM %s.\n",old_sem?"reset":"set");
01216   //  if (TB_R8(ISTAT,SIGP) != old_sigp)
01217   //    printf("SYM: SIGP %s.\n",old_sigp?"reset":"set");
01218   if(TB_R8(ISTAT, SIGP))
01219   {
01220     if(state.wait_reselect)
01221     {
01222 
01223       //      printf("SYM: SIGP while wait_reselect. Jumping...\n");
01224       R32(DSP) = state.wait_jump;
01225       state.wait_reselect = false;
01226       state.executing = true;
01227       mySemaphore.set();
01228     }
01229   }
01230 
01231   eval_interrupts();
01232 }
01233 
01246 u8 CSym53C810::read_b_ctest2()
01247 {
01248   SB_R8(CTEST2, CIO, pci_state.config_data[0][4] != 0);
01249   SB_R8(CTEST2, CM, pci_state.config_data[0][5] != 0);
01250   SB_R8(CTEST2, SIGP, TB_R8(ISTAT, SIGP));
01251   SB_R8(ISTAT, SIGP, false);
01252 
01253   //  printf("SYM: SIGP cleared by CTEST2 read.\n");
01254   return R8(CTEST2);
01255 }
01256 
01270 void CSym53C810::write_b_ctest3(u8 value)
01271 {
01272   WRM_R8(CTEST3, value);
01273 
01274   //if ((value>>3) & 1)
01275   //  printf("SYM: Don't know how to flush DMA FIFO\n");
01276   //if ((value>>2) & 1)
01277   //  printf("SYM: Don't know how to clear DMA FIFO\n");
01278   if((value >> 1) & 1)
01279     FAILURE(NotImplemented, "SYM: Don't know how to handle FM mode");
01280 }
01281 
01292 void CSym53C810::write_b_ctest4(u8 value)
01293 {
01294   R8(CTEST4) = value;
01295 
01296   if((value >> 4) & 1)
01297     FAILURE(NotImplemented, "SYM: Don't know how to handle SRTM mode");
01298 }
01299 
01318 void CSym53C810::write_b_ctest5(u8 value)
01319 {
01320   WRM_R8(CTEST5, value);
01321 
01322   if((value >> 7) & 1)
01323     FAILURE(NotImplemented, "SYM: Don't know how to do Clock Address increment");
01324 
01325   if((value >> 6) & 1)
01326     FAILURE(NotImplemented,
01327             "SYM: Don't know how to do Clock Byte Counter decrement");
01328 }
01329 
01336 u8 CSym53C810::read_b_dstat()
01337 {
01338   u8  retval = R8(DSTAT);
01339 
01340   RDCLR_R8(DSTAT);
01341 
01342   //printf("Read DSTAT --> eval int\n");
01343   eval_interrupts();
01344 
01345   //printf("Read DSTAT <-- eval int; retval: %02x; dstat: %02x.\n",retval,R8(DSTAT));
01346   return retval;
01347 }
01348 
01355 u8 CSym53C810::read_b_sist(int id)
01356 {
01357   u8  retval = state.regs.reg8[R_SIST0 + id];
01358 
01359   if(id)
01360     RDCLR_R8(SIST1);
01361   else
01362     RDCLR_R8(SIST0);
01363 
01364   eval_interrupts();
01365 
01366   return retval;
01367 }
01368 
01381 void CSym53C810::write_b_dcntl(u8 value)
01382 {
01383   WRM_R8(DCNTL, value);
01384 
01385   // start operation
01386   if(value & R_DCNTL_STD)
01387   {
01388     state.executing = true;
01389     mySemaphore.set();
01390   }
01391 
01392   //IRQD bit...
01393   eval_interrupts();
01394 }
01395 
01407 void CSym53C810::write_b_stest2(u8 value)
01408 {
01409   WRM_R8(STEST2, value);
01410 
01411   //  if (value & R_STEST2_ROF)
01412   //    printf("SYM: Don't know how to reset SCSI offset!\n");
01413   if(TB_R8(STEST2, LOW))
01414     FAILURE(NotImplemented, "SYM: I don't like LOW level mode");
01415 }
01416 
01424 void CSym53C810::write_b_stest3(u8 value)
01425 {
01426   WRM_R8(STEST3, value);
01427 
01428   //  if (value & R_STEST3_CSF)
01429   //    printf("SYM: Don't know how to clear the SCSI fifo.\n");
01430 }
01431 
01437 void CSym53C810::post_dsp_write()
01438 {
01439   if(!TB_R8(DMODE, MAN))
01440   {
01441     state.executing = true;
01442     mySemaphore.set();
01443 
01444     //printf("SYM: Execution started @ %08x.\n",R32(DSP));
01445   }
01446 }
01447 
01451 void CSym53C810::check_state()
01452 {
01453   if(myThread && !myThread->isRunning())
01454     FAILURE(Thread, "SYM thread has died");
01455 
01456   if(state.gen_timer)
01457   {
01458     state.gen_timer--;
01459     if(!state.gen_timer)
01460     {
01461       state.gen_timer = (R8(STIME1) & R_STIME1_GEN) * 30;
01462       RAISE(SIST1, GEN);
01463       return;
01464     }
01465   }
01466 
01488   if(state.disconnected)
01489   {
01490     if(!TB_R8(SCNTL2, SDU))
01491     {
01492 
01493       // disconnect expected
01494       //printf("SYM: Disconnect expected. stopping disconnect timer at %d.\n",state.disconnected);
01495       state.disconnected = 0;
01496       return;
01497     }
01498 
01499     state.disconnected--;
01500     if(!state.disconnected)
01501     {
01502 
01503       //printf("SYM: Disconnect unexpected. raising interrupt!\n");
01504       //printf(">");
01505       //getchar();
01506       RAISE(SIST0, UDC);
01507       return;
01508     }
01509   }
01510 }
01511 
01518 int CSym53C810::check_phase(int chk_phase)
01519 {
01520   int real_phase = scsi_get_phase(0);
01521 
01522   if(real_phase == SCSI_PHASE_ARBITRATION)
01523   {
01524 #if defined(DEBUG_SYM_SCRIPTS)
01525     printf("Phase check... selection time-out!\n");
01526 #endif
01527     RAISE(SIST1, STO);  // select time-out
01528     scsi_free(0);
01529     state.select_timeout = false;
01530     return -1;
01531   }
01532 
01533   if(real_phase == SCSI_PHASE_FREE && state.disconnected)
01534   {
01535 #if defined(DEBUG_SYM_SCRIPTS)
01536     printf("Phase check... disconnected!\n");
01537 #endif
01538     state.disconnected = 1;
01539     R32(DSP) -= 8;
01540     return -1;
01541   }
01542 
01543   if (real_phase == chk_phase)
01544     return 1;
01545   else
01546     return 0;
01547 }
01548 
01584 void CSym53C810::execute_bm_op()
01585 {
01586   bool  indirect = (R8(DCMD) >> 5) & 1;
01587   bool  table_indirect = (R8(DCMD) >> 4) & 1;
01588   int   opcode = (R8(DCMD) >> 3) & 1;
01589   int   scsi_phase = (R8(DCMD) >> 0) & 7;
01590 
01591 #if defined(DEBUG_SYM_SCRIPTS)
01592   printf("SYM: INS = Block Move (i %d, t %d, opc %d, phase %d\n", indirect,
01593          table_indirect, opcode, scsi_phase);
01594 #endif
01595   // Compare phase
01596   if(check_phase(scsi_phase)>0)
01597   {
01598 #if defined(DEBUG_SYM_SCRIPTS)
01599     printf("SYM: Ready for transfer.\n");
01600 #endif
01601 
01602     u32 start;
01603     u32 count;
01604 
01605     if(table_indirect)
01606     {
01607       u32 add = R32(DSA) + sext_u32_24(R32(DSPS));
01608 
01609       add &= ~0x03;       // 810
01610 #if defined(DEBUG_SYM_SCRIPTS)
01611       printf("SYM: Reading table at DSA(%08x)+DSPS(%08x) = %08x.\n",
01612              R32(DSA), R32(DSPS), add);
01613 #endif
01614       do_pci_read(add, &count, 4, 1);
01615       count &= 0x00ffffff;
01616       do_pci_read(add + 4, &start, 4, 1);
01617     }
01618     else if(indirect)
01619     {
01620       FAILURE(NotImplemented, "SYM: Unsupported: indirect addressing");
01621     }
01622     else
01623     {
01624       start = R32(DSPS);
01625       count = GET_DBC();
01626     }
01627 
01628 #if defined(DEBUG_SYM_SCRIPTS)
01629     printf("SYM: %08x: MOVE Start/count %x, %x\n", R32(DSP) - 8, start,
01630            count);
01631 #endif
01632     R32(DNAD) = start;
01633     SET_DBC(count);       // page 5-32
01634     if(count == 0)
01635     {
01636 
01637       //printf("SYM: Count equals zero!\n");
01638       RAISE(DSTAT, IID);  // page 5-32
01639       return;
01640     }
01641 
01642     if((size_t) count > scsi_expected_xfer(0))
01643     {
01644 #if defined(DEBUG_SYM_SCRIPTS)
01645       printf("SYM: xfer %d bytes, max %d expected, in phase %d.\n", count,
01646              scsi_expected_xfer(0), scsi_phase);
01647 #endif
01648       count = (u32) scsi_expected_xfer(0);
01649     }
01650 
01651     u8*   scsi_data_ptr = (u8*) scsi_xfer_ptr(0, count);
01652     u8*   org_sdata_ptr = scsi_data_ptr;
01653 
01654     switch(scsi_phase)
01655     {
01656     case SCSI_PHASE_COMMAND:
01657     case SCSI_PHASE_DATA_OUT:
01658     case SCSI_PHASE_MSG_OUT:
01659       do_pci_read(R32(DNAD), scsi_data_ptr, 1, count);
01660       R32(DNAD) += count;
01661       break;
01662 
01663     case SCSI_PHASE_STATUS:
01664     case SCSI_PHASE_DATA_IN:
01665     case SCSI_PHASE_MSG_IN:
01666       do_pci_write(R32(DNAD), scsi_data_ptr, 1, count);
01667       R32(DNAD) += count;
01668       break;
01669     }
01670 
01671     R8(SFBR) = *org_sdata_ptr;
01672     scsi_xfer_done(0);
01673     return;
01674   }
01675 }
01676 
01677 /* Execute one SCRIPTS I/O instruction
01678  * 
01679  * The I/O instructions perform common SCSI hardware sequences, like
01680  * Selection and reselection. The instruction format in
01681  * the DCMD and DBC register is as follows:
01682  *
01683  * \code
01684  * +---+-----+-+-+-+
01685  * |7 6|5 4 3|2|1|0| DCMD Register
01686  * +---+-----+-+-+-+
01687  *   |    |   | | +- 0: Select with ATN/:
01688  *   |    |   | |       Valid only for Select instruction. Assert ATN/ during 
01689  *   |    |   | |       selection
01690  *   |    |   | +- 1: Table Indirect Mode:
01691  *   |    |   |         0: All information is taken from the instruction,
01692  *   |    |   |            and the contents of the SCNTL3 and SXFER registers.
01693  *   |    |   |         1: The DSPS register contains a 24-bit signed offset
01694  *   |    |   |            that is added to the DSA register to get a pointer
01695  *   |    |   |            to a data structure that contains the destination
01696  *   |    |   |            ID, SCNTL3 bits, and SXFER bits. This structure 
01697  *   |    |   |            is 32 bits long and looks as follows:
01698  *   |    |   |                        +--------+--------+--------+--------+
01699  *   |    |   |            DSA+DSPS:   | SCNTL3 | ID     | SXFER  |        |
01700  *   |    |   |                        +--------+--------+--------+--------+
01701  *   |    |   +- 2: Relative Addrressing:
01702  *   |    |           0: The value in the DNAD register is an absolute address.
01703  *   |    |           1: The value in the DNAD register is a 24-bit signed
01704  *   |    |              displacement from the current DSP address.
01705  *   |    +- 3..5: Op Code
01706  *   +- 6..7 Instruction Type: 01 = I/O
01707  *
01708  * +-------+-------++--------+--+-+-++-+-+---+-+-----+
01709  * |       |19   16||        |10|9| || |6|   |3|     | DBC Register
01710  * +-------+-------++--------+--+-+-++-+-+---+-+-----+
01711  *             |              |  |      |     +- 3: Set/Clear ATN
01712  *             |              |  |      +- 6: Set/Clear ACK
01713  *             |              |  +- 9: Set/Clear Target Mode
01714  *             |              +- 10: Set/Clear Carry
01715  *             +- 16..19: Destination ID
01716  * \endcode
01717  *
01718  * The Opcode determines the actual instruction:
01719  * \code
01720  * +-----+-----------------+-------------+
01721  * | OPC | Initiator mode  | Target Mode |
01722  * +-----+-----------------+-------------+
01723  * | 000 | Select          | Reselect    |
01724  * | 001 | Wait Disconnect | Disconnect  |
01725  * | 010 | Wait Reselect   | Wait Select |
01726  * | 011 | Set             | Set         |
01727  * | 100 | Clear           | Clear       |
01728  * +-----+-----------------+-------------+
01729  * \endcode
01730  *
01731  * Select:
01732  *   - Arbitrate for the SCSI bus until arbitration is won.
01733  *   - If arbitration is won, try to select the destination ID
01734  *   - If the controller is selected or reselected before winning
01735  *     arbitration, jump to the address in the DNAD register.
01736  *   .
01737  *
01738  * Wait Disconnect:
01739  *   - Wait for the target to disconnect from the SCSI bus.
01740  *   .
01741  *
01742  * Wait Reselect:
01743  *   - If the controller is reselected, go to the next instruction.
01744  *   - If the controller is selected before being reselected, or if
01745  *     the CPU sets the SIGP flag, jump to the address in the DNAD 
01746  *     register
01747  *   .
01748  *
01749  * Set/Clear:
01750  *   - Set or Clear the flags whose Set/Clear bits are set in the
01751  *     instruction.
01752  *   .
01753  **/
01754 void CSym53C810::execute_io_op()
01755 {
01756   int   opcode = (R8(DCMD) >> 3) & 7;
01757   bool  relative = (R8(DCMD) >> 2) & 1;
01758   bool  table_indirect = (R8(DCMD) >> 1) & 1;
01759   bool  atn = (R8(DCMD) >> 0) & 1;
01760   int   destination = (GET_DBC() >> 16) & 0x0f;
01761   bool  sc_carry = (GET_DBC() >> 10) & 1;
01762   bool  sc_target = (GET_DBC() >> 9) & 1;
01763   bool  sc_ack = (GET_DBC() >> 6) & 1;
01764   bool  sc_atn = (GET_DBC() >> 3) & 1;
01765 
01766   R32(DNAD) = R32(DSPS);
01767 
01768   u32 dest_addr = R32(DNAD);
01769 
01770   if(relative)
01771     dest_addr = R32(DSP) + sext_u32_24(R32(DNAD));
01772 
01773 #if defined(DEBUG_SYM_SCRIPTS)
01774   printf("SYM: INS = I/O (opc %d, r %d, t %d, a %d, dest %d, sc %d%d%d%d\n",
01775          opcode, relative, table_indirect, atn, destination, sc_carry,
01776          sc_target, sc_ack, sc_atn);
01777 #endif
01778   if(table_indirect)
01779   {
01780     u32 io_addr = R32(DSA) + sext_u32_24(GET_DBC());
01781     io_addr &= ~3;      //810
01782 #if defined(DEBUG_SYM_SCRIPTS)
01783     printf("SYM: Reading table at DSA(%08x)+DBC(%08x) = %08x.\n",
01784            R32(DSA), sext_u32_24(GET_DBC()), io_addr);
01785 #endif
01786 
01787     u32 io_struc;
01788     do_pci_read(io_addr, &io_struc, 4, 1);
01789     destination = (io_struc >> 16) & 0x0f;
01790 #if defined(DEBUG_SYM_SCRIPTS)
01791     printf("SYM: table indirect. io_struct = %08x, new dest = %d.\n",
01792            io_struc, destination);
01793 #endif
01794   }
01795 
01796   switch(opcode)
01797   {
01798   case 0:
01799 #if defined(DEBUG_SYM_SCRIPTS)
01800     printf("SYM: %08x: SELECT %d.\n", R32(DSP) - 8, destination);
01801 #endif
01802     SET_DEST(destination);
01803     if(!scsi_arbitrate(0))
01804     {
01805 
01806       // scsi bus busy, try again next clock...
01807       printf("scsi bus busy...\n");
01808       R32(DSP) -= 8;
01809       return;
01810     }
01811 
01812     state.select_timeout = !scsi_select(0, destination);
01813     if(!state.select_timeout)   // select ok
01814       SB_R8(SCNTL2, SDU, true); // don't expect a disconnect
01815     return;
01816 
01817   case 1:
01818 #if defined(DEBUG_SYM_SCRIPTS)
01819     printf("SYM: %08x: WAIT DISCONNECT\n", R32(DSP) - 8);
01820 #endif
01821 
01822     // maybe we need to do more??
01823     scsi_free(0);
01824     return;
01825 
01826   case 2:
01827 #if defined(DEBUG_SYM_SCRIPTS)
01828     printf("SYM: %08x: WAIT RESELECT\n", R32(DSP) - 8);
01829 #endif
01830     if(TB_R8(ISTAT, SIGP))
01831     {
01832 #if defined(DEBUG_SYM_SCRIPTS)
01833       printf("SYM: SIGP set before wait reselect; jumping!\n");
01834 #endif
01835       R32(DSP) = dest_addr;
01836     }
01837     else
01838     {
01839       state.wait_reselect = true;
01840       state.wait_jump = dest_addr;
01841       state.executing = false;
01842     }
01843 
01844     return;
01845 
01846   case 3:
01847 #if defined(DEBUG_SYM_SCRIPTS)
01848     printf("SYM: %08x: SET %s%s%s%s\n", R32(DSP) - 8,
01849            sc_carry ? "carry " : "", sc_target ? "target " : "",
01850            sc_ack ? "ack " : "", sc_atn ? "atn " : "");
01851 #endif
01852     if(sc_ack)
01853       SB_R8(SOCL, ACK, true);
01854     if(sc_atn)
01855     {
01856       if(!TB_R8(SOCL, ATN))
01857       {
01858         SB_R8(SOCL, ATN, true);
01859 
01860         //printf("SET ATN.\n");
01861         //printf(">");
01862         //getchar();
01863       }
01864     }
01865 
01866     if(sc_target)
01867       SB_R8(SCNTL0, TRG, true);
01868     if(sc_carry)
01869       state.alu.carry = true;
01870     return;
01871 
01872   case 4:
01873 #if defined(DEBUG_SYM_SCRIPTS)
01874     printf("SYM: %08x: CLEAR %s%s%s%s\n", R32(DSP) - 8,
01875            sc_carry ? "carry " : "", sc_target ? "target " : "",
01876            sc_ack ? "ack " : "", sc_atn ? "atn " : "");
01877 #endif
01878     if(sc_ack)
01879       SB_R8(SOCL, ACK, false);
01880     if(sc_atn)
01881     {
01882       if(TB_R8(SOCL, ATN))
01883       {
01884         SB_R8(SOCL, ATN, false);
01885 
01886         //printf("RESET ATN.\n");
01887         //printf(">");
01888         //getchar();
01889       }
01890     }
01891 
01892     if(sc_target)
01893       SB_R8(SCNTL0, TRG, false);
01894     if(sc_carry)
01895       state.alu.carry = false;
01896     return;
01897 
01898     break;
01899   }
01900 }
01901 
01939 void CSym53C810::execute_rw_op()
01940 {
01941   int   opcode = (R8(DCMD) >> 3) & 7;
01942   int   oper = (R8(DCMD) >> 0) & 7;
01943   bool  use_data8_sfbr = (GET_DBC() >> 23) & 1;
01944   int   reg_address = ((GET_DBC() >> 16) & 0x7f); //| (GET_DBC() & 0x80); // manual is unclear about bit 7.
01945   u8    imm_data = (u8) (GET_DBC() >> 8) & 0xff;
01946   u8    op_data;
01947 
01948 #if defined(DEBUG_SYM_SCRIPTS)
01949   printf("SYM: INS = R/W (opc %d, oper %d, use %d, add %d, imm %02x\n",
01950          opcode, oper, use_data8_sfbr, reg_address, imm_data);
01951 #endif
01952   if(use_data8_sfbr)
01953     imm_data = R8(SFBR);
01954 
01955   if(oper != 0)
01956   {
01957     if(opcode == 5 || reg_address == 0x08)
01958     {
01959       op_data = R8(SFBR);
01960 #if defined(DEBUG_SYM_SCRIPTS)
01961       printf("SYM: %08x: sfbr (%02x) ", R32(DSP) - 8, op_data);
01962 #endif
01963     }
01964     else
01965     {
01966       op_data = (u8) ReadMem_Bar(0, 1, reg_address, 8);
01967 #if defined(DEBUG_SYM_SCRIPTS)
01968       printf("SYM: %08x: reg%02x (%02x) ", R32(DSP) - 8, reg_address,
01969              op_data);
01970 #endif
01971     }
01972   }
01973 
01974   u16 tmp16;
01975 
01976   switch(oper)
01977   {
01978   case 0:
01979     op_data = imm_data;
01980 #if defined(DEBUG_SYM_SCRIPTS)
01981     printf("SYM: %08x: %02x ", R32(DSP) - 8, imm_data);
01982 #endif
01983     break;
01984 
01985   case 1:
01986     tmp16 = (op_data << 1) + (state.alu.carry ? 1 : 0);
01987     state.alu.carry = (tmp16 >> 8) & 1;
01988     op_data = tmp16 & 0xff;
01989 #if defined(DEBUG_SYM_SCRIPTS)
01990     printf("<< 1 = %02x ", op_data);
01991 #endif
01992     break;
01993 
01994   case 2:
01995     op_data |= imm_data;
01996 #if defined(DEBUG_SYM_SCRIPTS)
01997     printf("| %02x = %02x ", imm_data, op_data);
01998 #endif
01999     break;
02000 
02001   case 3:
02002     op_data ^= imm_data;
02003 #if defined(DEBUG_SYM_SCRIPTS)
02004     printf("^ %02x = %02x ", imm_data, op_data);
02005 #endif
02006     break;
02007 
02008   case 4:
02009     op_data &= imm_data;
02010 #if defined(DEBUG_SYM_SCRIPTS)
02011     printf("& %02x = %02x ", imm_data, op_data);
02012 #endif
02013     break;
02014 
02015   case 5:
02016     tmp16 = (op_data >> 1) + (state.alu.carry ? 0x80 : 0x00);
02017     state.alu.carry = op_data & 1;
02018     op_data = tmp16 & 0xff;
02019 #if defined(DEBUG_SYM_SCRIPTS)
02020     printf(">> 1 = %02x ", op_data);
02021 #endif
02022     break;
02023 
02024   case 6:
02025     tmp16 = op_data + imm_data;
02026     state.alu.carry = (tmp16 > 0xff);
02027     op_data = tmp16 & 0xff;
02028 #if defined(DEBUG_SYM_SCRIPTS)
02029     printf("+ %02x = %02x (carry %d) ", imm_data, op_data, state.alu.carry);
02030 #endif
02031     break;
02032 
02033   case 7:
02034     tmp16 = op_data + imm_data + (state.alu.carry ? 1 : 0);
02035     state.alu.carry = (tmp16 > 0xff);
02036     op_data = tmp16 & 0xff;
02037 #if defined(DEBUG_SYM_SCRIPTS)
02038     printf("+ %02x (w/carry) = %02x (carry %d) ", imm_data, op_data,
02039            state.alu.carry);
02040 #endif
02041     break;
02042   }
02043 
02044   if(opcode == 6 || reg_address == 0x08)
02045   {
02046 #if defined(DEBUG_SYM_SCRIPTS)
02047     printf("-> sfbr.\n");
02048 #endif
02049     R8(SFBR) = op_data;
02050   }
02051   else
02052   {
02053 #if defined(DEBUG_SYM_SCRIPTS)
02054     printf("-> reg%02x.\n", reg_address);
02055 #endif
02056     WriteMem_Bar(0, 1, reg_address, 8, op_data);
02057   }
02058 }
02059 
02134 void CSym53C810::execute_tc_op()
02135 {
02136   int   opcode = (R8(DCMD) >> 3) & 7;
02137   int   scsi_phase = (R8(DCMD) >> 0) & 7;
02138   bool  relative = (GET_DBC() >> 23) & 1;
02139   bool  carry_test = (GET_DBC() >> 21) & 1;
02140   bool  interrupt_fly = (GET_DBC() >> 20) & 1;
02141   bool  jump_if = (GET_DBC() >> 19) & 1;
02142   bool  cmp_data = (GET_DBC() >> 18) & 1;
02143   bool  cmp_phase = (GET_DBC() >> 17) & 1;
02144   int   cmp_mask = (GET_DBC() >> 8) & 0xff;
02145   int   cmp_dat = (GET_DBC() >> 0) & 0xff;
02146   u32   dest_addr;
02147 
02148   // wait_valid can be safely ignored, phases are always valid in this ideal world...
02149   // bool wait_valid = (GET_DBC()>>16) & 1;
02150 
02151   // We'll keep modifying this variable until we know what the result of the comparisons is.
02152   bool  do_it;
02153 
02154   // Relative jump or not? (no effect on Return or Interrupt)
02155   if(relative)
02156     dest_addr = R32(DSP) + sext_u32_24(R32(DSPS));
02157   else
02158     dest_addr = R32(DSPS);
02159 
02160 #if defined(DEBUG_SYM_SCRIPTS)
02161   printf("SYM: %08x: if (", R32(DSP) - 8);
02162 #endif
02163   if(carry_test)
02164   {
02165     // All we need to check is the CARRY flag
02166 #if defined(DEBUG_SYM_SCRIPTS)
02167     printf("(%scarry)", jump_if ? "" : "!");
02168 #endif
02169     do_it = (state.alu.carry == jump_if);
02170   }
02171   else if(cmp_data || cmp_phase)
02172   {
02173     // We need to compare data and/or phase
02174     do_it = true;
02175     if(cmp_data)
02176     {
02177       // compare data
02178 #if defined(DEBUG_SYM_SCRIPTS)
02179       printf("((data & 0x%02x) %s 0x%02x)", (~cmp_mask) & 0xff,
02180              jump_if ? "==" : "!=", cmp_dat &~cmp_mask);
02181 #endif
02182       if(((R8(SFBR) &~cmp_mask) == (cmp_dat &~cmp_mask)) != jump_if)
02183         do_it = false;
02184 #if defined(DEBUG_SYM_SCRIPTS)
02185       if(cmp_phase)
02186         printf(" && ");
02187 #endif
02188     }
02189 
02190     if(cmp_phase)
02191     {
02192       // Compare phase
02193 #if defined(DEBUG_SYM_SCRIPTS)
02194       printf("(phase %s %d)", jump_if ? "==" : "!=", scsi_phase);
02195 #endif
02196       if((check_phase(scsi_phase)>0) != jump_if)
02197         do_it = false;
02198     }
02199   }
02200   else
02201   {
02202 
02203     // no comparison
02204     do_it = jump_if;
02205   }
02206 
02207 #if defined(DEBUG_SYM_SCRIPTS)
02208   printf(") ");
02209 #endif
02210   switch(opcode)
02211   {
02212   case 0:
02213 #if defined(DEBUG_SYM_SCRIPTS)
02214     printf("jump %x\n", R32(DSPS));
02215 #endif
02216     if(do_it)
02217     {
02218 #if defined(DEBUG_SYM_SCRIPTS)
02219       printf("SYM: Jumping %08x...\n", dest_addr);
02220 #endif
02221       R32(DSP) = dest_addr;
02222     }
02223 
02224     return;
02225     break;
02226 
02227   case 1:
02228 #if defined(DEBUG_SYM_SCRIPTS)
02229     printf("call %d\n", R32(DSPS));
02230 #endif
02231     if(do_it)
02232     {
02233 #if defined(DEBUG_SYM_SCRIPTS)
02234       printf("SYM: Calling %08x...\n", dest_addr);
02235 #endif
02236       R32(TEMP) = R32(DSP);
02237       R32(DSP) = dest_addr;
02238     }
02239 
02240     return;
02241     break;
02242 
02243   case 2:
02244 #if defined(DEBUG_SYM_SCRIPTS)
02245     printf("return %d\n", R32(DSPS));
02246 #endif
02247     if(do_it)
02248     {
02249 #if defined(DEBUG_SYM_SCRIPTS)
02250       printf("SYM: Returning %08x...\n", R32(TEMP));
02251 #endif
02252       R32(DSP) = R32(TEMP);
02253     }
02254 
02255     return;
02256     break;
02257 
02258   case 3:
02259 #if defined(DEBUG_SYM_SCRIPTS)
02260     printf("interrupt%s.\n", interrupt_fly ? " on the fly" : "");
02261 #endif
02262     if(do_it)
02263     {
02264 #if defined(DEBUG_SYM_SCRIPTS)
02265       printf("SYM: Interrupt with vector %x...\n", R32(DSPS));
02266 #endif
02267       if(interrupt_fly)
02268         RAISE(ISTAT, INTF);
02269       else
02270         RAISE(DSTAT, SIR);
02271     }
02272 
02273     return;
02274     break;
02275 
02276   default:
02277     FAILURE_1(NotImplemented,
02278               "SYM: Transfer Control Instruction with opcode %d is RESERVED.\n",
02279               opcode);
02280   }
02281 }
02282 
02314 void CSym53C810::execute_ls_op()
02315 {
02316   bool  is_load = (R8(DCMD) >> 0) & 1;
02317   bool  no_flush = (R8(DCMD) >> 1) & 1;
02318   bool  dsa_relative = (R8(DCMD) >> 4) & 1;
02319   int   regaddr = (GET_DBC() >> 16) & 0x7f;
02320   int   byte_count = (GET_DBC() >> 0) & 7;
02321   u32   memaddr;
02322 
02323   // Relative Addressing
02324   if(dsa_relative)
02325     memaddr = R32(DSA) + sext_u32_24(R32(DSPS));
02326   else
02327     memaddr = R32(DSPS);
02328 
02329 #if defined(DEBUG_SYM_SCRIPTS)
02330   printf("SYM: dsa_rel: %d, DSA: %04x, DSPS: %04x, mem %04x.\n",
02331          dsa_relative, R32(DSA), R32(DSPS), memaddr);
02332 #endif
02333   if(is_load)
02334   {
02335 #if defined(DEBUG_SYM_SCRIPTS)
02336     printf("SYM: %08x: Load reg%02x", R32(DSP) - 8, regaddr);
02337     if(byte_count > 1)
02338       printf("..%02x", regaddr + byte_count - 1);
02339     printf("from %x.\n", memaddr);
02340 #endif
02341     // Perform Load Operation
02342     for(int i = 0; i < byte_count; i++)
02343     {
02344       u8  dat;
02345       do_pci_read(memaddr + i, &dat, 1, 1);
02346 #if defined(DEBUG_SYM_SCRIPTS)
02347       printf("SYM: %02x -> reg%02x\n", dat, regaddr + i);
02348 #endif
02349       WriteMem_Bar(0, 1, regaddr + i, 8, dat);
02350     }
02351   }
02352   else
02353   {
02354 #if defined(DEBUG_SYM_SCRIPTS)
02355     printf("SYM: %08x: Store reg%02x", R32(DSP) - 8, regaddr);
02356     if(byte_count > 1)
02357       printf("..%02x", regaddr + byte_count - 1);
02358     printf("to %x.\n", memaddr);
02359 #endif
02360     // Perform Store Operation
02361     for(int i = 0; i < byte_count; i++)
02362     {
02363       u8  dat = (u8) ReadMem_Bar(0, 1, regaddr + i, 8);
02364 #if defined(DEBUG_SYM_SCRIPTS)
02365       printf("SYM: %02x <- reg%02x\n", dat, regaddr + i);
02366 #endif
02367       do_pci_write(memaddr + i, &dat, 1, 1);
02368     }
02369   }
02370 }
02371 
02394 void CSym53C810::execute_mm_op()
02395 {
02396   u32 temp_shadow;
02397   do_pci_read(R32(DSP), &temp_shadow, 4, 1);
02398   R32(DSP) += 4;
02399 
02400 #if defined(DEBUG_SYM_SCRIPTS)
02401   printf("SYM: %08x: Memory Move %06x bytes from %08x to %08x.\n",
02402          R32(DSP) - 12, GET_DBC(), R32(DSPS), temp_shadow);
02403 #endif
02404 
02405   // To speed things up, we set up a buffer and read all data
02406   // at once, followed by writing all data at once.
02407   void*   buf = malloc(GET_DBC());
02408   do_pci_read(R32(DSPS), buf, 1, GET_DBC());
02409   do_pci_write(temp_shadow, buf, 1, GET_DBC());
02410   free(buf);
02411   return;
02412 }
02413 
02433 void CSym53C810::execute()
02434 {
02435   int optype;
02436   int opcode;
02437   bool is_load_store;
02438 
02439 #if defined(DEBUG_SYM_SCRIPTS)
02440       printf("SYM: INS @ %x   \n",R32(DSP));
02441 #endif
02442 
02443   // Read 2 DWORDS into the DCMD, DBC and DSPS registers.
02444   do_pci_read(R32(DSP), &R32(DBC), 4, 1);
02445   do_pci_read(R32(DSP) + 4, &R32(DSPS), 4, 1);
02446 
02447   // Increase DSP to point to the next instruction
02448   R32(DSP) += 8;
02449 
02450 #if defined(DEBUG_SYM_SCRIPTS)
02451   printf("SYM: INS = %x, %x, %x   \n", R8(DCMD), GET_DBC(), R32(DSPS));
02452 #endif
02453   /* The two most significant bits of the DCMD register determine the operation
02454    * type. These are:
02455    *   00: Block Move
02456    *   01: I/O or R/W
02457    *   10: Transfer Control
02458    *   11: Memory Move or Load And Store
02459    */
02460   optype = (R8(DCMD) >> 6) & 3;
02461   switch(optype)
02462   {
02463   case 0:
02464     execute_bm_op();
02465     break;
02466 
02467   case 1:
02468     opcode = (R8(DCMD) >> 3) & 7;
02469     if(opcode < 5)
02470       execute_io_op();
02471     else
02472       execute_rw_op();
02473     break;
02474 
02475   case 2:
02476     execute_tc_op();
02477     break;
02478 
02479   case 3:
02480     is_load_store = (R8(DCMD) >> 5) & 1;
02481     if(is_load_store)
02482       execute_ls_op();
02483     else
02484       execute_mm_op();
02485     break;
02486   }
02487 
02488   // single step mode
02489   if(TB_R8(DCNTL, SSM))
02490   {
02491 #if defined(DEBUG_SYM_SCRIPTS)
02492     printf("SYM: Single step...\n");
02493 #endif
02494     RAISE(DSTAT, SSI);
02495   }
02496 }
02497 
02526 void CSym53C810::set_interrupt(int reg, u8 interrupt)
02527 {
02528   //printf("set interrupt %02x, %02x.\n",reg,interrupt);
02529   switch(reg)
02530   {
02531   case R_DSTAT:
02532     if(TB_R8(ISTAT, DIP) || TB_R8(ISTAT, SIP))
02533     {
02534       state.dstat_stack |= interrupt;
02535 
02536       //printf("DSTAT stacked.\n");
02537     }
02538     else
02539     {
02540       R8(DSTAT) |= interrupt;
02541 
02542       //printf("DSTAT.\n");
02543     }
02544     break;
02545 
02546   case R_SIST0:
02547     if(TB_R8(ISTAT, DIP) || TB_R8(ISTAT, SIP))
02548     {
02549       state.sist0_stack |= interrupt;
02550 
02551       //printf("SIST0 stacked.\n");
02552     }
02553     else
02554     {
02555       R8(SIST0) |= interrupt;
02556 
02557       //printf("SIST0.\n");
02558     }
02559     break;
02560 
02561   case R_SIST1:
02562     if(TB_R8(ISTAT, DIP) || TB_R8(ISTAT, SIP))
02563     {
02564       state.sist1_stack |= interrupt;
02565 
02566       //printf("SIST1 stacked.\n");
02567     }
02568     else
02569     {
02570       R8(SIST1) |= interrupt;
02571 
02572       //printf("SIST1.\n");
02573     }
02574     break;
02575 
02576   case R_ISTAT:
02577 
02578     //printf("ISTAT.\n");
02579     R8(ISTAT) |= interrupt;
02580     break;
02581 
02582   default:
02583     FAILURE_1(NotImplemented, "set_interrupt reg %02x!!\n", reg);
02584   }
02585 
02586   //printf("--> eval int\n");
02587   eval_interrupts();
02588 
02589   //printf("<-- eval_int\n");
02590 }
02591 
02597 void CSym53C810::eval_interrupts()
02598 {
02599   // will_assert: when this boolean value is true at the end of this function, an
02600   // interrupt will be signalled to the system.
02601   bool  will_assert = false;
02602   
02603   // will_halt: when this boolean value is true at the end of this function,
02604   // program execution will be halted. (fatal interrupt)
02605   bool  will_halt = false;
02606 
02607   // Check current interrupt status. If no interrupt is active, move interrupt
02608   // flags from the interrupt stack down.
02609   //
02610   // (When an interrupt is signalled, but another interrupt bit is already active,
02611   // the interrupt doesn't go to the interrupt register, but to the interrupt 
02612   // stack. The interrupt stack, however, doesn't keep track of the order in which
02613   // interrupts come in, so when the interrupt stack is moved down into the 
02614   // interrupt registers, multiple interrupt bits may become active.)
02615   if(!R8(SIST0) && !R8(SIST1) && !R8(DSTAT))
02616   {
02617     R8(SIST0) |= state.sist0_stack;
02618     R8(SIST1) |= state.sist1_stack;
02619     R8(DSTAT) |= state.dstat_stack;
02620     state.sist0_stack = 0;
02621     state.sist1_stack = 0;
02622     state.dstat_stack = 0;
02623   }
02624 
02625   // Check for DMA interrupts.
02626   if(R8(DSTAT) & DSTAT_FATAL)
02627   {
02628     // DMA interrupt conditions always halt execution (always fatal)
02629     will_halt = true;
02630 
02631     //printf("  will halt(DSTAT).\n");
02632 
02633     // Set the DMA interrupt pending bit.
02634     SB_R8(ISTAT, DIP, true);
02635 
02636     // If the interrupt is also enabled in the DIEN register, it will
02637     // be signalled to the system.
02638     if(R8(DSTAT) & R8(DIEN) & DSTAT_FATAL)
02639     {
02640       will_assert = true;
02641 
02642       //printf("  will assert(DSTAT).\n");
02643     }
02644   }
02645   else
02646   {
02647     // Reset the DMA interrupt pending bit. (It may still be set).
02648     SB_R8(ISTAT, DIP, false);
02649   }
02650 
02651   // Check for SCSI engine interrupts
02652   if(R8(SIST0) || R8(SIST1))
02653   {
02654     // Set the SCSI interrupt pending bit.
02655     SB_R8(ISTAT, SIP, true);
02656 
02657     //Check if the interrupt is either fatal, or enabled.
02658     if((R8(SIST0) & (SIST0_FATAL | R8(SIEN0)))
02659      || (R8(SIST1) & (SIST1_FATAL | R8(SIEN1))))
02660     {
02661       // In either case, stop execution.
02662       will_halt = true;
02663 
02664       //printf("  will halt(SIST).\n");
02665 
02666       // If the interrupt is enabled, signal it to the system.
02667       if((R8(SIST0) & R8(SIEN0)) || (R8(SIST1) & R8(SIEN1)))
02668       {
02669         will_assert = true;
02670 
02671         //printf("  will assert(SIST).\n");
02672       }
02673     }
02674   }
02675   else
02676   {
02677     // Reset the SCSI interrupt pending bit (It may still be set).
02678     SB_R8(ISTAT, SIP, false);
02679   }
02680 
02681   // Check the interrupt on the fly bit.
02682   if(TB_R8(ISTAT, INTF))
02683   {
02684     // Signal this to the system
02685     will_assert = true;
02686 
02687     //printf("  will assert(INTF).\n");
02688   }
02689 
02690   // If interrupts are disabled, don't signal any interrupt to the system.
02691   if(TB_R8(DCNTL, IRQD))
02692   {
02693     will_assert = false;
02694 
02695     //printf("  won't assert(IRQD).\n");
02696   }
02697 
02698   // Halt execution if will_halt is true.
02699   if(will_halt)
02700     state.executing = false;
02701 
02702   // Assert or de-assert the interrupt line as needed
02703   if(will_assert != state.irq_asserted)
02704   {
02705 
02706     //printf("  doing...%d\n",will_assert);
02707     do_pci_interrupt(0, will_assert);
02708     state.irq_asserted = will_assert;
02709   }
02710 }

SourceForge.net Logo
Project space on SourceForge.net