Sym53C895.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 
00132 #if defined(DEBUG_SYM)
00133 #define DEBUG_SYM_REGS
00134 #define DEBUG_SYM_SCRIPTS
00135 #endif
00136 #include "StdAfx.h"
00137 #include "Sym53C895.h"
00138 #include "System.h"
00139 #include "Disk.h"
00140 #include "SCSIBus.h"
00141 
00143 #define R_SCNTL0          0x00
00144 #define R_SCNTL0_ARB1     0x80
00145 #define R_SCNTL0_ARB0     0x40
00146 #define R_SCNTL0_START    0x20
00147 #define R_SCNTL0_WATN     0x10
00148 #define R_SCNTL0_EPC      0x08
00149 #define R_SCNTL0_AAP      0x02
00150 #define R_SCNTL0_TRG      0x01
00151 #define SCNTL0_MASK       0xFB
00152 
00154 #define R_SCNTL1          0x01
00155 #define R_SCNTL1_CON      0x10
00156 #define R_SCNTL1_RST      0x08
00157 #define R_SCNTL1_IARB     0x02
00158 
00160 #define R_SCNTL2          0x02
00161 #define R_SCNTL2_SDU      0x80
00162 #define R_SCNTL2_CHM      0x40
00163 #define R_SCNTL2_SLPMD    0x20
00164 #define R_SCNTL2_SLPHBEN  0x10
00165 #define R_SCNTL2_WSS      0x08
00166 #define R_SCNTL2_VUE0     0x04
00167 #define R_SCNTL2_VUE1     0x02
00168 #define R_SCNTL2_WSR      0x01
00169 #define SCNTL2_MASK       0xF2
00170 #define SCNTL2_W1C        0x09
00171 
00173 #define R_SCNTL3          0x03
00174 #define R_SCNTL3_EWS      0x08
00175 
00177 #define R_SCID            0x04
00178 #define R_SCID_ID         0x0F
00179 #define SCID_MASK         0x6F
00180 
00182 #define R_SXFER           0x05
00183 
00185 #define R_SDID            0x06
00186 #define R_SDID_ID         0x0F
00187 #define SDID_MASK         0x0F
00188 
00190 #define R_GPREG           0x07
00191 #define GPREG_MASK        0x1F
00192 
00194 #define R_SFBR            0x08
00195 
00197 #define R_SOCL            0x09
00198 #define R_SOCL_ACK        0x40
00199 #define R_SOCL_ATN        0x20
00200 
00202 #define R_SSID            0x0A
00203 #define R_SSID_VAL        0x80
00204 #define R_SSID_ID         0x0F
00205 
00207 #define R_SBCL            0x0B
00208 #define R_SBCL_REQ        0x80
00209 #define R_SBCL_ACK        0x40
00210 #define R_SBCL_BSY        0x20
00211 #define R_SBCL_SEL        0x10
00212 #define R_SBCL_ATN        0x08
00213 #define R_SBCL_MSG        0x04
00214 #define R_SBCL_CD         0x02
00215 #define R_SBCL_IO         0x01
00216 #define R_SBCL_PHASE      0x07
00217 
00219 #define R_DSTAT           0x0C
00220 #define R_DSTAT_DFE       0x80
00221 #define R_DSTAT_MDPE      0x40
00222 #define R_DSTAT_BF        0x20
00223 #define R_DSTAT_ABRT      0x10
00224 #define R_DSTAT_SSI       0x08
00225 #define R_DSTAT_SIR       0x04
00226 #define R_DSTAT_IID       0x01
00227 #define DSTAT_RC          0x7D
00228 #define DSTAT_FATAL       0x7D
00229 
00231 #define R_SSTAT0          0x0D
00232 #define R_SSTAT0_RST      0x02
00233 #define R_SSTAT0_SDP0     0x01
00234 
00236 #define R_SSTAT1          0x0E
00237 #define R_SSTAT1_SDP1     0x01
00238 
00240 #define R_SSTAT2          0x0F
00241 #define R_SSTAT2_LDSC     0x02
00242 
00244 #define R_DSA             0x10
00245 
00247 #define R_ISTAT           0x14
00248 #define R_ISTAT_ABRT      0x80
00249 #define R_ISTAT_SRST      0x40
00250 #define R_ISTAT_SIGP      0x20
00251 #define R_ISTAT_SEM       0x10
00252 #define R_ISTAT_CON       0x08
00253 #define R_ISTAT_INTF      0x04
00254 #define R_ISTAT_SIP       0x02
00255 #define R_ISTAT_DIP       0x01
00256 #define ISTAT_MASK        0xF0
00257 #define ISTAT_W1C         0x04
00258 
00260 #define R_CTEST0          0x18
00261 
00263 #define R_CTEST1          0x19
00264 #define R_CTEST1_FMT      0xF0
00265 #define R_CTEST1_FFL      0x0F
00266 
00268 #define R_CTEST2          0x1A
00269 #define R_CTEST2_DDIR     0x80
00270 #define R_CTEST2_SIGP     0x40
00271 #define R_CTEST2_CIO      0x20
00272 #define R_CTEST2_CM       0x10
00273 #define R_CTEST2_SRTCH    0x08
00274 #define R_CTEST2_TEOP     0x04
00275 #define R_CTEST2_DREQ     0x02
00276 #define R_CTEST2_DACK     0x01
00277 #define CTEST2_MASK       0x08
00278 
00280 #define R_CTEST3          0x1B
00281 #define R_CTEST3_REV      0xf0
00282 #define R_CTEST3_FLF      0x08
00283 #define R_CTEST3_CLF      0x04
00284 #define R_CTEST3_FM       0x02
00285 #define CTEST3_MASK       0x0B
00286 
00288 #define R_TEMP            0x1C
00289 
00291 #define R_DFIFO           0x20
00292 
00294 #define R_CTEST4          0x21
00295 
00297 #define R_CTEST5          0x22
00298 #define R_CTEST5_ADCK     0x80
00299 #define R_CTEST5_BBCK     0x40
00300 #define CTEST5_MASK       0x3F
00301 
00303 #define R_CTEST6          0x23
00304 
00306 #define R_DBC             0x24
00307 
00309 #define R_DCMD            0x27
00310 
00312 #define R_DNAD            0x28
00313 
00315 #define R_DSP             0x2C
00316 
00318 #define R_DSPS            0x30
00319 
00321 #define R_SCRATCHA        0x34
00322 
00324 #define R_DMODE           0x38
00325 #define R_DMODE_MAN       0x01
00326 
00328 #define R_DIEN            0x39
00329 #define DIEN_MASK         0x7D
00330 
00332 #define R_SBR             0x3A
00333 
00335 #define R_DCNTL           0x3B
00336 #define R_DCNTL_SSM       0x10
00337 #define R_DCNTL_STD       0x04
00338 #define R_DCNTL_IRQD      0x02
00339 #define R_DCNTL_COM       0x01
00340 #define DCNTL_MASK        0xFB
00341 
00343 #define R_ADDER           0x3C
00344 
00346 #define R_SIEN0           0x40
00347 #define SIEN0_MASK        0xFF
00348 
00350 #define R_SIEN1           0x41
00351 #define SIEN1_MASK        0x17
00352 
00354 #define R_SIST0           0x42
00355 #define R_SIST0_MA        0x80
00356 #define R_SIST0_CMP       0x40
00357 #define R_SIST0_SEL       0x20
00358 #define R_SIST0_RSL       0x10
00359 #define R_SIST0_SGE       0x08
00360 #define R_SIST0_UDC       0x04
00361 #define R_SIST0_RST       0x02
00362 #define R_SIST0_PAR       0x01
00363 #define SIST0_RC          0xFF
00364 #define SIST0_FATAL       0x8F
00365 
00367 #define R_SIST1           0x43
00368 #define R_SIST1_SBMC      0x10
00369 #define R_SIST1_STO       0x04
00370 #define R_SIST1_GEN       0x02
00371 #define R_SIST1_HTH       0x01
00372 #define SIST1_RC          0x17
00373 #define SIST1_FATAL       0x14
00374 
00376 #define R_SLPAR           0x44
00377 
00379 #define R_SWIDE           0x45
00380 
00382 #define R_MACNTL          0x46
00383 #define MACNTL_MASK       0x0F
00384 
00386 #define R_GPCNTL          0x47
00387 
00389 #define R_STIME0          0x48
00390 
00392 #define R_STIME1          0x49
00393 #define R_STIME1_GEN      0x0F
00394 #define STIME1_MASK       0x7F
00395 
00397 #define R_RESPID          0x4A
00398 
00400 #define R_STEST0          0x4C
00401 
00403 #define R_STEST1          0x4D
00404 #define STEST1_MASK       0xCC
00405 
00407 #define R_STEST2          0x4E
00408 #define R_STEST2_SCE      0x80
00409 #define R_STEST2_ROF      0x40
00410 #define R_STEST2_DIF      0x20
00411 #define R_STEST2_SLB      0x10
00412 #define R_STEST2_SZM      0x08
00413 #define R_STEST2_AWS      0x04
00414 #define R_STEST2_EXT      0x02
00415 #define R_STEST2_LOW      0x01
00416 #define STEST2_MASK       0xBF
00417 
00419 #define R_STEST3          0x4F
00420 #define R_STEST3_TE       0x80
00421 #define R_STEST3_STR      0x40
00422 #define R_STEST3_HSC      0x20
00423 #define R_STEST3_DSI      0x10
00424 #define R_STEST3_S16      0x08
00425 #define R_STEST3_TTM      0x04
00426 #define R_STEST3_CSF      0x02
00427 #define R_STEST3_STW      0x01
00428 #define STEST3_MASK       0xFF
00429 
00431 #define R_SIDL            0x50
00432 
00434 #define R_STEST4          0x52
00435 
00437 #define R_SODL            0x54
00438 
00440 #define R_SBDL            0x58
00441 
00443 #define R_SCRATCHB        0x5C
00444 
00446 #define R_SCRATCHC        0x60
00447 
00449 #define R8(a)             state.regs.reg8[R_##a]
00450 
00452 #define R16(a)            state.regs.reg16[R_##a / 2]
00453 
00455 #define R32(a)            state.regs.reg32[R_##a / 4]
00456 
00463 #define TB_R8(a, b) ((R8(a) & R_##a##_##b) == R_##a##_##b)
00464 
00472 #define SB_R8(a, b, c)  R8(a) = (R8(a) &~R_##a##_##b) | (c ? R_##a##_##b : 0)
00473 
00482 #define WRM_R8(a, b)  R8(a) = (R8(a) &~a##_MASK) | ((b) & a##_MASK)
00483 
00494 #define WRMW1C_R8(a, b)                    \
00495     R8(a) = (R8(a) &~a##_MASK &~a##_W1C) | \
00496     ((b) & a##_MASK) |                     \
00497     (R8(a) &~(b) & a##_W1C)
00498 
00505 #define RAISE(a, b) set_interrupt(R_##a, R_##a##_##b)
00506 
00514 #define RDCLR_R8(a) R8(a) &= ~a##_RC
00515 
00519 #define GET_DEST()  (R8(SDID) & R_SCID_ID)
00520 
00524 #define SET_DEST(a) R8(SDID) = (a) & R_SCID_ID
00525 
00529 #define GET_DBC()   (R32(DBC) & 0x00ffffff)
00530 
00534 #define SET_DBC(a)                       \
00535     R32(DBC) = (R32(DBC) & 0xff000000) | \
00536     ((a) & 0x00ffffff)
00537 
00541 u32 sym_cfg_data[64] =
00542 {
00543   /*00*/  0x000c1000,         // CFID: vendor + device
00544   /*04*/  0x02000001,         // CFCS: command + status
00545   /*08*/  0x01000000,         // CFRV: class + revision
00546   /*0c*/  0x00000000,         // CFLT: latency timer + cache line size
00547   /*10*/  0x00000001,         // BAR0: IO Space
00548   /*14*/  0x00000000,         // BAR1: Memory space
00549   /*18*/  0x00000000,         // BAR2: RAM space
00550   /*1c*/  0x00000000,         // BAR3:
00551   /*20*/  0x00000000,         // BAR4:
00552   /*24*/  0x00000000,         // BAR5:
00553   /*28*/  0x00000000,         // CCIC: CardBus
00554   /*2c*/  0x00000000,         // CSID: subsystem + vendor
00555   /*30*/  0x00000000,         // BAR6: expansion rom base
00556   /*34*/  0x00000000,         // CCAP: capabilities pointer
00557   /*38*/  0x00000000,
00558   /*3c*/  0x401101ff,         // CFIT: interrupt configuration
00559   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00560   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00561   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00562 };
00563 
00567 u32 sym_cfg_mask[64] = {
00568   /*00*/ 0x00000000,  // CFID: vendor + device
00569   /*04*/ 0x00000157,  // CFCS: command + status
00570   /*08*/ 0x00000000,  // CFRV: class + revision
00571   /*0c*/ 0x0000ffff,  // CFLT: latency timer + cache line size
00572   /*10*/ 0xffffff00,  // BAR0: IO space (256 bytes)
00573   /*14*/ 0xffffff00,  // BAR1: Memory space (256 bytes)
00574   /*18*/ 0xfffff000,  // BAR2: RAM space (4KB)
00575   /*1c*/ 0x00000000,  // BAR3:
00576   /*20*/ 0x00000000,  // BAR4:
00577   /*24*/ 0x00000000,  // BAR5:
00578   /*28*/ 0x00000000,  // CCIC: CardBus
00579   /*2c*/ 0x00000000,  // CSID: subsystem + vendor
00580   /*30*/ 0x00000000,  // BAR6: expansion rom base
00581   /*34*/ 0x00000000,  // CCAP: capabilities pointer
00582   /*38*/ 0x00000000,
00583   /*3c*/ 0x000000ff,  // CFIT: interrupt configuration
00584   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00585   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00586   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00587 };
00588 
00597 void CSym53C895::run()
00598 {
00599   try
00600   {
00601     for(;;)
00602     {
00603       mySemaphore.wait();
00604       if(StopThread)
00605         return;
00606       while(state.executing)
00607       {
00608         MUTEX_LOCK(myRegLock);
00609         execute();
00610         MUTEX_UNLOCK(myRegLock);
00611       }
00612     }
00613   }
00614 
00615   catch(Poco::Exception & e)
00616   {
00617     printf("Exception in SYM thread: %s.\n", e.displayText().c_str());
00618 
00619     // Let the thread die...
00620   }
00621 }
00622 
00629 CSym53C895::CSym53C895(CConfigurator* cfg, CSystem* c, int pcibus, int pcidev) : CDiskController(cfg, c, pcibus, pcidev, 1, 16), mySemaphore(0, 1)
00630 {
00631 
00632   // create scsi bus
00633   CSCSIBus*   a = new CSCSIBus(cfg, c);
00634   scsi_register(0, a, 7); // scsi id 7 by default
00635 }
00636 
00642 void CSym53C895::init()
00643 {
00644   add_function(0, sym_cfg_data, sym_cfg_mask);
00645 
00646   ResetPCI();
00647 
00648   chip_reset();
00649 
00650   myRegLock = new CMutex("sym-reg");
00651 
00652   myThread = 0;
00653 
00654   printf("%s: $Id: Sym53C895.cpp,v 1.33 2008/03/25 16:05:30 iamcamiel Exp $\n",
00655          devid_string);
00656 }
00657 
00661 void CSym53C895::start_threads()
00662 {
00663   if(!myThread)
00664   {
00665     myThread = new Poco::Thread("sym");
00666     printf(" %s", myThread->getName().c_str());
00667     StopThread = false;
00668     myThread->start(*this);
00669     if(state.executing)
00670       mySemaphore.set();
00671   }
00672 }
00673 
00677 void CSym53C895::stop_threads()
00678 {
00679   StopThread = true;
00680   if(myThread)
00681   {
00682     printf(" %s", myThread->getName().c_str());
00683     mySemaphore.set();
00684     myThread->join();
00685     delete myThread;
00686     myThread = 0;
00687   }
00688 }
00689 
00695 CSym53C895::~CSym53C895()
00696 {
00697   stop_threads();
00698   delete scsi_bus[0];
00699 }
00700 
00706 void CSym53C895::chip_reset()
00707 {
00708   state.executing = false;
00709   state.wait_reselect = false;
00710   state.irq_asserted = false;
00711   state.gen_timer = 0;
00712   memset(state.regs.reg32, 0, sizeof(state.regs.reg32));
00713   R8(SCNTL0) = R_SCNTL0_ARB1 | R_SCNTL0_ARB0; // 810
00714   R8(DSTAT) = R_DSTAT_DFE;    // DMA FIFO empty // 810
00715 
00716   //  R8(SSTAT2) = R_SSTAT2_LDSC; // 810
00717   R8(CTEST1) = R_CTEST1_FMT;  // 810
00718   R8(CTEST2) = R_CTEST2_DACK; // 810
00719   R8(CTEST3) = (u8) (pci_state.config_data[0][2] << 4) & R_CTEST3_REV;  // Chip rev.
00720   R8(MACNTL) = 0xD0;  // 895 type ID
00721   R8(GPCNTL) = 0x0F;  // 810
00722   R8(STEST0) = 0x03;  // 810
00723 }
00724 
00730 void CSym53C895::register_disk(class CDisk* dsk, int bus, int dev)
00731 {
00732   CDiskController::register_disk(dsk, bus, dev);
00733   dsk->scsi_register(0, scsi_bus[0], dev);
00734 }
00735 
00737 static u32  sym_magic1 = 0x53C895CC;
00739 static u32  sym_magic2 = 0xCC53C895;
00740 
00744 int CSym53C895::SaveState(FILE* f)
00745 {
00746   long  ss = sizeof(state);
00747   int   res;
00748 
00749   if(res = CPCIDevice::SaveState(f))
00750     return res;
00751 
00752   fwrite(&sym_magic1, sizeof(u32), 1, f);
00753   fwrite(&ss, sizeof(long), 1, f);
00754   fwrite(&state, sizeof(state), 1, f);
00755   fwrite(&sym_magic2, sizeof(u32), 1, f);
00756   printf("%s: %d bytes saved.\n", devid_string, (int) ss);
00757   return 0;
00758 }
00759 
00763 int CSym53C895::RestoreState(FILE* f)
00764 {
00765   long    ss;
00766   u32     m1;
00767   u32     m2;
00768   int     res;
00769   size_t  r;
00770 
00771   if(res = CPCIDevice::RestoreState(f))
00772     return res;
00773 
00774   r = fread(&m1, sizeof(u32), 1, f);
00775   if(r != 1)
00776   {
00777     printf("%s: unexpected end of file!\n", devid_string);
00778     return -1;
00779   }
00780 
00781   if(m1 != sym_magic1)
00782   {
00783     printf("%s: MAGIC 1 does not match!\n", devid_string);
00784     return -1;
00785   }
00786 
00787   fread(&ss, sizeof(long), 1, f);
00788   if(r != 1)
00789   {
00790     printf("%s: unexpected end of file!\n", devid_string);
00791     return -1;
00792   }
00793 
00794   if(ss != sizeof(state))
00795   {
00796     printf("%s: STRUCT SIZE does not match!\n", devid_string);
00797     return -1;
00798   }
00799 
00800   fread(&state, sizeof(state), 1, f);
00801   if(r != 1)
00802   {
00803     printf("%s: unexpected end of file!\n", devid_string);
00804     return -1;
00805   }
00806 
00807   r = fread(&m2, sizeof(u32), 1, f);
00808   if(r != 1)
00809   {
00810     printf("%s: unexpected end of file!\n", devid_string);
00811     return -1;
00812   }
00813 
00814   if(m2 != sym_magic2)
00815   {
00816     printf("%s: MAGIC 1 does not match!\n", devid_string);
00817     return -1;
00818   }
00819 
00820   printf("%s: %d bytes restored.\n", devid_string, (int) ss);
00821   return 0;
00822 }
00823 
00827 void CSym53C895::WriteMem_Bar(int func, int bar, u32 address, int dsize, u32 data)
00828 {
00829   void*   p;
00830 
00831   switch(bar)
00832   {
00833   case 0:
00834   case 1:
00835     address &= 0x7f;
00836     switch(dsize)
00837     {
00838     case 8:
00839       MUTEX_LOCK(myRegLock);
00840 #if defined(DEBUG_SYM_REGS)
00841       printf("SYM: Write to register %02x: %02x.   \n", address, data);
00842 #endif
00843       if(address >= R_SCRATCHC)
00844       {
00845         state.regs.reg8[address] = (u8) data;
00846         MUTEX_UNLOCK(myRegLock);
00847         break;
00848       }
00849 
00850       switch(address)
00851       {
00852 
00853       // SIMPLE CASES: JUST WRITE
00854       case R_SXFER:             // 05
00855       case R_DSA:               // 10
00856       case R_DSA + 1:           // 11
00857       case R_DSA + 2:           // 12
00858       case R_DSA + 3:           // 13
00859       case R_CTEST0:            // 18
00860       case R_TEMP:              // 1C
00861       case R_TEMP + 1:          // 1D
00862       case R_TEMP + 2:          // 1E
00863       case R_TEMP + 3:          // 1F
00864       case R_DSP:               // 2C
00865       case R_DSP + 1:           // 2D
00866       case R_DSP + 2:           // 2E
00867       case R_DSPS:              // 30
00868       case R_DSPS + 1:          // 31
00869       case R_DSPS + 2:          // 32
00870       case R_DSPS + 3:          // 33
00871       case R_SCRATCHA:          // 34
00872       case R_SCRATCHA + 1:      // 35
00873       case R_SCRATCHA + 2:      // 36
00874       case R_SCRATCHA + 3:      // 37
00875       case R_DMODE:             // 38
00876       case R_SBR:               // 3A     // 810
00877       case R_GPCNTL:            // 47
00878       case R_STIME0:            // 48
00879       case R_RESPID:            // 4A
00880       case R_RESPID + 1:        // 4B
00881       case R_STEST0:            // 4C
00882       case R_SCRATCHB:          // 5C
00883       case R_SCRATCHB + 1:      // 5D
00884       case R_SCRATCHB + 2:      // 5E
00885       case R_SCRATCHB + 3:      // 5F
00886         state.regs.reg8[address] = (u8) data;
00887         break;
00888 
00889       case R_SCNTL0:            // 00
00890         // side effects: start arbitration bit
00891         write_b_scntl0((u8) data);
00892         break;
00893 
00894       case R_SCNTL1:            //01
00895         // side effects: start immediate arbitration bit
00896         write_b_scntl1((u8) data);
00897         break;
00898 
00899       case R_SCNTL2:            //02
00900         WRMW1C_R8(SCNTL2, (u8) data);
00901         break;
00902 
00903       case R_SCNTL3:            //03
00904         // side effects: clearing EWS
00905         write_b_scntl3((u8) data);
00906         break;
00907 
00908       case R_SCID:              // 04
00909         WRM_R8(SCID, (u8) data);
00910         break;
00911 
00912       case R_SDID:              // 06
00913         WRM_R8(SDID, (u8) data);
00914         break;
00915 
00916       case R_GPREG:             // 07
00917         WRM_R8(GPREG, (u8) data);
00918         break;
00919 
00920       case R_ISTAT:             // 14
00921         write_b_istat((u8) data);
00922         break;
00923 
00924       case R_CTEST2:            // 1A
00925         WRM_R8(CTEST2, (u8) data);
00926         break;
00927 
00928       case R_CTEST3:            // 1B
00929         write_b_ctest3((u8) data);
00930         break;
00931 
00932       case R_CTEST4:            // 21
00933         write_b_ctest4((u8) data);
00934         break;
00935 
00936       case R_CTEST5:            // 22
00937         write_b_ctest5((u8) data);
00938         break;
00939 
00940       case R_DSP + 3:           // 2F
00941         state.regs.reg8[address] = (u8) data;
00942         post_dsp_write();
00943         break;
00944 
00945       case R_DIEN:              // 39
00946         WRM_R8(DIEN, (u8) data);
00947         eval_interrupts();
00948         break;
00949 
00950       case R_DCNTL:             // 3B
00951         write_b_dcntl((u8) data);
00952         break;
00953 
00954       case R_SIEN0:             // 40
00955         R8(SIEN0) = (u8) data;
00956         eval_interrupts();
00957         break;
00958 
00959       case R_SIEN1:             // 41
00960         WRM_R8(SIEN1, (u8) data);
00961         eval_interrupts();
00962         break;
00963 
00964       case R_MACNTL:            // 46     // 810
00965         WRM_R8(MACNTL, (u8) data);
00966         break;
00967 
00968       case R_STIME1:            // 49
00969         WRM_R8(STIME1, (u8) data);
00970         state.gen_timer = (R8(STIME1) & R_STIME1_GEN) * 30;
00971         break;
00972 
00973       case R_STEST1:            // 4D
00974         WRM_R8(STEST1, (u8) data);
00975         break;
00976 
00977       case R_STEST2:            // 4E
00978         write_b_stest2((u8) data);
00979         break;
00980 
00981       case R_STEST3:            // 4F
00982         write_b_stest3((u8) data);
00983         break;
00984 
00985       case R_DSTAT:             // 0C
00986       case R_SSTAT0:            // 0D
00987       case R_SSTAT1:            // 0E
00988       case R_SSTAT2:            // 0F
00989         //printf("SYM: Write to read-only memory at %02x. FreeBSD driver cache test.\n" ,address);
00990         break;
00991 
00992       default:
00993         FAILURE_2(NotImplemented,
00994                   "SYM: Write to unknown register at %02x with %08x.\n", address,
00995                   data);
00996       }
00997 
00998       MUTEX_UNLOCK(myRegLock);
00999       break;
01000 
01001     case 16:
01002       WriteMem_Bar(0, 1, address + 0, 8, (data >> 0) & 0xff);
01003       WriteMem_Bar(0, 1, address + 1, 8, (data >> 8) & 0xff);
01004       break;
01005 
01006     case 32:
01007       WriteMem_Bar(0, 1, address + 0, 8, (data >> 0) & 0xff);
01008       WriteMem_Bar(0, 1, address + 1, 8, (data >> 8) & 0xff);
01009       WriteMem_Bar(0, 1, address + 2, 8, (data >> 16) & 0xff);
01010       WriteMem_Bar(0, 1, address + 3, 8, (data >> 24) & 0xff);
01011       break;
01012     }
01013     break;
01014 
01015   case 2:
01016     p = (u8*) state.ram + address;
01017     switch(dsize)
01018     {
01019     case 8:   *((u8*) p) = (u8) data; break;
01020     case 16:  *((u16*) p) = (u16) data; break;
01021     case 32:  *((u32*) p) = (u32) data; break;
01022     }
01023     break;
01024   }
01025 }
01026 
01030 u32 CSym53C895::ReadMem_Bar(int func, int bar, u32 address, int dsize)
01031 {
01032   u32     data = 0;
01033   void*   p;
01034 
01035   switch(bar)
01036   {
01037   case 0:
01038   case 1:
01039     address &= 0x7f;
01040     switch(dsize)
01041     {
01042     case 8:
01043       MUTEX_LOCK(myRegLock);
01044       if(address >= R_SCRATCHC)
01045       {
01046         data = state.regs.reg8[address];
01047         MUTEX_UNLOCK(myRegLock);
01048         break;
01049       }
01050 
01051       switch(address)
01052       {
01053       case R_SCNTL0:            // 00
01054       case R_SCNTL1:            // 01
01055       case R_SCNTL2:            // 02
01056       case R_SCNTL3:            // 03
01057       case R_SCID:              // 04
01058       case R_SXFER:             // 05
01059       case R_SDID:              // 06
01060       case R_GPREG:             // 07
01061       case R_SFBR:              // 08
01062       case R_SSID:              // 0A
01063       case R_SBCL:              // 0B
01064       case R_SSTAT0:            // 0D
01065       case R_SSTAT1:            // 0E
01066       case R_SSTAT2:            // 0F
01067       case R_DSA:               // 10
01068       case R_DSA + 1:           // 11
01069       case R_DSA + 2:           // 12
01070       case R_DSA + 3:           // 13
01071       case R_ISTAT:             // 14
01072       case R_CTEST0:            // 18
01073       case R_CTEST1:            // 19
01074       case R_CTEST3:            // 1B
01075       case R_TEMP:              // 1C
01076       case R_TEMP + 1:          // 1D
01077       case R_TEMP + 2:          // 1E
01078       case R_TEMP + 3:          // 1F
01079       case R_CTEST4:            // 21
01080       case R_CTEST5:            // 22
01081       case R_DBC:               // 24  // 810
01082       case R_DBC + 1:           // 25  // 810
01083       case R_DBC + 2:           // 26  // 810
01084       case R_DCMD:              // 27  // 810
01085       case R_DNAD:              // 28  // 810
01086       case R_DNAD + 1:          // 29  // 810
01087       case R_DNAD + 2:          // 2A  // 810
01088       case R_DNAD + 3:          // 2B  // 810
01089       case R_DSP:               // 2C
01090       case R_DSP + 1:           // 2D
01091       case R_DSP + 2:           // 2E
01092       case R_DSP + 3:           // 2F
01093       case R_DSPS:              // 30
01094       case R_DSPS + 1:          // 31
01095       case R_DSPS + 2:          // 32
01096       case R_DSPS + 3:          // 33
01097       case R_DMODE:             // 38
01098       case R_DIEN:              // 39
01099       case R_SBR:               // 3A     // 810
01100       case R_DCNTL:             // 3B
01101       case R_SIEN0:             // 40
01102       case R_SIEN1:             // 41
01103       case R_MACNTL:            // 46     // 810
01104       case R_GPCNTL:            // 47
01105       case R_STIME0:            // 48
01106       case R_STIME1:            // 49
01107       case R_RESPID:            // 4A
01108       case R_RESPID + 1:        // 4B
01109       case R_STEST0:            // 4C
01110       case R_STEST1:            // 4D
01111       case R_STEST2:            // 4E
01112       case R_STEST3:            // 4F
01113       case R_STEST4:            // 52
01114       case R_SBDL:              // 58
01115       case R_SBDL + 1:          // 59
01116         data = state.regs.reg8[address];
01117         break;
01118 
01119       case R_DSTAT:             // 0C
01120         data = read_b_dstat();
01121         break;
01122 
01123       case R_CTEST2:            // 1A
01124         data = read_b_ctest2();
01125         break;
01126 
01127       case R_DFIFO:             // 20
01128         data = R8(DBC) & 0x7f;  // 810 - fake the DFIFO count
01129         break;
01130 
01131       case R_SCRATCHA:          // 34
01132       case R_SCRATCHA + 1:      // 35
01133       case R_SCRATCHA + 2:      // 36
01134       case R_SCRATCHA + 3:      // 37
01135         data = read_b_scratcha(address - R_SCRATCHA);
01136         break;
01137 
01138       case R_SIST0:         // 42
01139       case R_SIST1:         // 43
01140         data = read_b_sist(address - R_SIST0);
01141         break;
01142 
01143       case R_SCRATCHB:      // 5C
01144       case R_SCRATCHB + 1:  // 5D
01145       case R_SCRATCHB + 2:  // 5E
01146       case R_SCRATCHB + 3:  // 5F
01147         data = read_b_scratchb(address - R_SCRATCHB);
01148         break;
01149 
01150       default:
01151         FAILURE_2(NotImplemented,
01152                   "SYM: Attempt to read from unknown register at %02x\n", dsize,
01153                   address);
01154       }
01155 
01156       MUTEX_UNLOCK(myRegLock);
01157 #if defined(DEBUG_SYM_REGS)
01158       printf("SYM: Read frm register %02x: %02x.   \n", address, data);
01159 #endif
01160       break;
01161 
01162     case 16:
01163       data = (ReadMem_Bar(0, 1, address + 0, 8) << 0) & 0x00ff;
01164       data |= (ReadMem_Bar(0, 1, address + 1, 8) << 8) & 0xff00;
01165       break;
01166 
01167     case 32:
01168       data = (ReadMem_Bar(0, 1, address + 0, 8) << 0) & 0x000000ff;
01169       data |= (ReadMem_Bar(0, 1, address + 1, 8) << 8) & 0x0000ff00;
01170       data |= (ReadMem_Bar(0, 1, address + 2, 8) << 16) & 0x00ff0000;
01171       data |= (ReadMem_Bar(0, 1, address + 3, 8) << 24) & 0xff000000;
01172       break;
01173     }
01174     break;
01175 
01176   case 2:
01177     p = (u8*) state.ram + address;
01178     switch(dsize)
01179     {
01180     case 8:   return *((u8*) p);
01181     case 16:  return *((u16*) p);
01182     case 32:  return *((u32*) p);
01183     }
01184     break;
01185   }
01186 
01187   return data;
01188 }
01189 
01196 u32 CSym53C895::config_read_custom(int func, u32 address, int dsize, u32 data)
01197 {
01198   if(address >= 0x80)
01199     return ReadMem_Bar(func, 1, address - 0x80, dsize);
01200   else
01201     return data;
01202 }
01203 
01210 void CSym53C895::config_write_custom(int func, u32 address, int dsize,
01211                                      u32 old_data, u32 new_data, u32 data)
01212 {
01213   if(address >= 0x80)
01214     WriteMem_Bar(func, 1, address - 0x80, dsize, data);
01215 }
01216 
01232 void CSym53C895::write_b_scntl0(u8 value)
01233 {
01234   bool  old_start = TB_R8(SCNTL0, START);
01235 
01236   WRM_R8(SCNTL0, value);
01237 
01238   if(TB_R8(SCNTL0, START) && !old_start)
01239     FAILURE(NotImplemented, "SYM: Don't know how to start arbitration sequence");
01240 
01241   if(TB_R8(SCNTL0, TRG))
01242     FAILURE(NotImplemented, "SYM: Don't know how to operate in target mode");
01243 }
01244 
01261 void CSym53C895::write_b_scntl1(u8 value)
01262 {
01263   bool  old_iarb = TB_R8(SCNTL1, IARB);
01264   bool  old_con = TB_R8(SCNTL1, CON);
01265   bool  old_rst = TB_R8(SCNTL1, RST);
01266 
01267   R8(SCNTL1) = value;
01268 
01269   //  if (TB_R8(SCNTL1,CON) != old_con)
01270   //    printf("SYM: Don't know how to forcibly connect or disconnect\n");
01271   if(TB_R8(SCNTL1, RST) != old_rst)
01272   {
01273     SB_R8(SSTAT0, SDP0, false);
01274     SB_R8(SSTAT1, SDP1, false);
01275     R16(SBDL) = 0;
01276     R8(SBCL) = 0;
01277 
01278     SB_R8(SSTAT0, RST, !old_rst);
01279 
01280     //    printf("SYM: %s SCSI bus reset.\n",old_rst?"end":"start");
01281     if(!old_rst)
01282       RAISE(SIST0, RST);
01283   }
01284 }
01285 
01292 void CSym53C895::write_b_scntl3(u8 value)
01293 {
01294   R8(SCNTL3) = value;
01295 
01296   /* If Wide SCSI is disabled, the Wide SCSI Receive flag can't
01297      be set. */
01298   if(!TB_R8(SCNTL3, EWS))
01299     SB_R8(SCNTL2, WSR, false);
01300 }
01301 
01318 void CSym53C895::write_b_istat(u8 value)
01319 {
01320   bool  old_srst = TB_R8(ISTAT, SRST);
01321   bool  old_sem = TB_R8(ISTAT, SEM);
01322   bool  old_sigp = TB_R8(ISTAT, SIGP);
01323 
01324   WRMW1C_R8(ISTAT, value);
01325 
01326   if(TB_R8(ISTAT, ABRT))
01327   {
01328 
01329     //    printf("SYM: Aborting on request.\n");
01330     RAISE(DSTAT, ABRT);
01331   }
01332 
01333   if(TB_R8(ISTAT, SRST) && !old_srst)
01334   {
01335 
01336     //    printf("SYM: Resetting on request.\n");
01337     chip_reset();
01338   }
01339 
01340   //  if (TB_R8(ISTAT,SEM) != old_sem)
01341   //    printf("SYM: SEM %s.\n",old_sem?"reset":"set");
01342   //  if (TB_R8(ISTAT,SIGP) != old_sigp)
01343   //    printf("SYM: SIGP %s.\n",old_sigp?"reset":"set");
01344   if(TB_R8(ISTAT, SIGP))
01345   {
01346     if(state.wait_reselect)
01347     {
01348 
01349       //      printf("SYM: SIGP while wait_reselect. Jumping...\n");
01350       R32(DSP) = state.wait_jump;
01351       state.wait_reselect = false;
01352       state.executing = true;
01353       mySemaphore.set();
01354     }
01355   }
01356 
01357   eval_interrupts();
01358 }
01359 
01372 u8 CSym53C895::read_b_ctest2()
01373 {
01374   SB_R8(CTEST2, CIO, pci_state.config_data[0][4] != 0);
01375   SB_R8(CTEST2, CM, pci_state.config_data[0][5] != 0);
01376   SB_R8(CTEST2, SIGP, TB_R8(ISTAT, SIGP));
01377   SB_R8(ISTAT, SIGP, false);
01378 
01379   //  printf("SYM: SIGP cleared by CTEST2 read.\n");
01380   return R8(CTEST2);
01381 }
01382 
01396 void CSym53C895::write_b_ctest3(u8 value)
01397 {
01398   WRM_R8(CTEST3, value);
01399 
01400   //if ((value>>3) & 1)
01401   //  printf("SYM: Don't know how to flush DMA FIFO\n");
01402   //if ((value>>2) & 1)
01403   //  printf("SYM: Don't know how to clear DMA FIFO\n");
01404   if((value >> 1) & 1)
01405     FAILURE(NotImplemented, "SYM: Don't know how to handle FM mode");
01406 }
01407 
01418 void CSym53C895::write_b_ctest4(u8 value)
01419 {
01420   R8(CTEST4) = value;
01421 
01422   if((value >> 4) & 1)
01423     FAILURE(NotImplemented, "SYM: Don't know how to handle SRTM mode");
01424 }
01425 
01444 void CSym53C895::write_b_ctest5(u8 value)
01445 {
01446   WRM_R8(CTEST5, value);
01447 
01448   if((value >> 7) & 1)
01449     FAILURE(NotImplemented, "SYM: Don't know how to do Clock Address increment");
01450 
01451   if((value >> 6) & 1)
01452     FAILURE(NotImplemented,
01453             "SYM: Don't know how to do Clock Byte Counter decrement");
01454 }
01455 
01462 u8 CSym53C895::read_b_dstat()
01463 {
01464   u8  retval = R8(DSTAT);
01465 
01466   RDCLR_R8(DSTAT);
01467 
01468   //printf("Read DSTAT --> eval int\n");
01469   eval_interrupts();
01470 
01471   //printf("Read DSTAT <-- eval int; retval: %02x; dstat: %02x.\n",retval,R8(DSTAT));
01472   return retval;
01473 }
01474 
01481 u8 CSym53C895::read_b_sist(int id)
01482 {
01483   u8  retval = state.regs.reg8[R_SIST0 + id];
01484 
01485   if(id)
01486     RDCLR_R8(SIST1);
01487   else
01488     RDCLR_R8(SIST0);
01489 
01490   eval_interrupts();
01491 
01492   return retval;
01493 }
01494 
01507 void CSym53C895::write_b_dcntl(u8 value)
01508 {
01509   WRM_R8(DCNTL, value);
01510 
01511   // start operation
01512   if(value & R_DCNTL_STD)
01513   {
01514     state.executing = true;
01515     mySemaphore.set();
01516   }
01517 
01518   //IRQD bit...
01519   eval_interrupts();
01520 }
01521 
01529 u8 CSym53C895::read_b_scratcha(int reg)
01530 {
01531   if(TB_R8(CTEST2, SRTCH))
01532   {
01533 
01534     //printf("SYM: SCRATCHA from PCI\n");
01535     return(u8) (pci_state.config_data[0][4] >> (reg * 8)) & 0xff;
01536   }
01537   else
01538     return state.regs.reg8[R_SCRATCHA + reg];
01539 }
01540 
01548 u8 CSym53C895::read_b_scratchb(int reg)
01549 {
01550   if(TB_R8(CTEST2, SRTCH))
01551   {
01552 
01553     //printf("SYM: SCRATCHB from PCI\n");
01554     return(u8) (pci_state.config_data[0][5] >> (reg * 8)) & 0xff;
01555   }
01556   else
01557     return state.regs.reg8[R_SCRATCHB + reg];
01558 }
01559 
01571 void CSym53C895::write_b_stest2(u8 value)
01572 {
01573   WRM_R8(STEST2, value);
01574 
01575   //  if (value & R_STEST2_ROF)
01576   //    printf("SYM: Don't know how to reset SCSI offset!\n");
01577   if(TB_R8(STEST2, LOW))
01578     FAILURE(NotImplemented, "SYM: I don't like LOW level mode");
01579 }
01580 
01588 void CSym53C895::write_b_stest3(u8 value)
01589 {
01590   WRM_R8(STEST3, value);
01591 
01592   //  if (value & R_STEST3_CSF)
01593   //    printf("SYM: Don't know how to clear the SCSI fifo.\n");
01594 }
01595 
01601 void CSym53C895::post_dsp_write()
01602 {
01603   if(!TB_R8(DMODE, MAN))
01604   {
01605     state.executing = true;
01606     mySemaphore.set();
01607 
01608     //printf("SYM: Execution started @ %08x.\n",R32(DSP));
01609   }
01610 }
01611 
01615 void CSym53C895::check_state()
01616 {
01617   if(myThread && !myThread->isRunning())
01618     FAILURE(Thread, "SYM thread has died");
01619 
01620   if(state.gen_timer)
01621   {
01622     state.gen_timer--;
01623     if(!state.gen_timer)
01624     {
01625       state.gen_timer = (R8(STIME1) & R_STIME1_GEN) * 30;
01626       RAISE(SIST1, GEN);
01627       return;
01628     }
01629   }
01630 
01652   if(state.disconnected)
01653   {
01654     if(!TB_R8(SCNTL2, SDU))
01655     {
01656 
01657       // disconnect expected
01658       //printf("SYM: Disconnect expected. stopping disconnect timer at %d.\n",state.disconnected);
01659       state.disconnected = 0;
01660       return;
01661     }
01662 
01663     state.disconnected--;
01664     if(!state.disconnected)
01665     {
01666 
01667       //printf("SYM: Disconnect unexpected. raising interrupt!\n");
01668       //printf(">");
01669       //getchar();
01670       RAISE(SIST0, UDC);
01671       return;
01672     }
01673   }
01674 }
01675 
01682 int CSym53C895::check_phase(int chk_phase)
01683 {
01684   int real_phase = scsi_get_phase(0);
01685 
01686   if(real_phase == SCSI_PHASE_ARBITRATION)
01687   {
01688 #if defined(DEBUG_SYM_SCRIPTS)
01689     printf("Phase check... selection time-out!\n");
01690 #endif
01691     RAISE(SIST1, STO);  // select time-out
01692     scsi_free(0);
01693     state.select_timeout = false;
01694     return -1;
01695   }
01696 
01697   if(real_phase == SCSI_PHASE_FREE && state.disconnected)
01698   {
01699 #if defined(DEBUG_SYM_SCRIPTS)
01700     printf("Phase check... disconnected!\n");
01701 #endif
01702     state.disconnected = 1;
01703     R32(DSP) -= 8;
01704     return -1;
01705   }
01706 
01707   if (real_phase == chk_phase)
01708     return 1;
01709   else
01710     return 0;
01711 }
01712 
01748 void CSym53C895::execute_bm_op()
01749 {
01750   bool  indirect = (R8(DCMD) >> 5) & 1;
01751   bool  table_indirect = (R8(DCMD) >> 4) & 1;
01752   int   opcode = (R8(DCMD) >> 3) & 1;
01753   int   scsi_phase = (R8(DCMD) >> 0) & 7;
01754 
01755 #if defined(DEBUG_SYM_SCRIPTS)
01756   printf("SYM: INS = Block Move (i %d, t %d, opc %d, phase %d\n", indirect,
01757          table_indirect, opcode, scsi_phase);
01758 #endif
01759   // Compare phase
01760   if(check_phase(scsi_phase)>0)
01761   {
01762 #if defined(DEBUG_SYM_SCRIPTS)
01763     printf("SYM: Ready for transfer.\n");
01764 #endif
01765 
01766     u32 start;
01767     u32 count;
01768 
01769     if(table_indirect)
01770     {
01771       u32 add = R32(DSA) + sext_u32_24(R32(DSPS));
01772 
01773       add &= ~0x03;       // 810
01774 #if defined(DEBUG_SYM_SCRIPTS)
01775       printf("SYM: Reading table at DSA(%08x)+DSPS(%08x) = %08x.\n",
01776              R32(DSA), R32(DSPS), add);
01777 #endif
01778       do_pci_read(add, &count, 4, 1);
01779       count &= 0x00ffffff;
01780       do_pci_read(add + 4, &start, 4, 1);
01781     }
01782     else if(indirect)
01783     {
01784       FAILURE(NotImplemented, "SYM: Unsupported: indirect addressing");
01785     }
01786     else
01787     {
01788       start = R32(DSPS);
01789       count = GET_DBC();
01790     }
01791 
01792 #if defined(DEBUG_SYM_SCRIPTS)
01793     printf("SYM: %08x: MOVE Start/count %x, %x\n", R32(DSP) - 8, start,
01794            count);
01795 #endif
01796     R32(DNAD) = start;
01797     SET_DBC(count);       // page 5-32
01798     if(count == 0)
01799     {
01800 
01801       //printf("SYM: Count equals zero!\n");
01802       RAISE(DSTAT, IID);  // page 5-32
01803       return;
01804     }
01805 
01806     if((size_t) count > scsi_expected_xfer(0))
01807     {
01808 #if defined(DEBUG_SYM_SCRIPTS)
01809       printf("SYM: xfer %d bytes, max %d expected, in phase %d.\n", count,
01810              scsi_expected_xfer(0), scsi_phase);
01811 #endif
01812       count = (u32) scsi_expected_xfer(0);
01813     }
01814 
01815     u8*   scsi_data_ptr = (u8*) scsi_xfer_ptr(0, count);
01816     u8*   org_sdata_ptr = scsi_data_ptr;
01817 
01818     switch(scsi_phase)
01819     {
01820     case SCSI_PHASE_COMMAND:
01821     case SCSI_PHASE_DATA_OUT:
01822     case SCSI_PHASE_MSG_OUT:
01823       do_pci_read(R32(DNAD), scsi_data_ptr, 1, count);
01824       R32(DNAD) += count;
01825       break;
01826 
01827     case SCSI_PHASE_STATUS:
01828     case SCSI_PHASE_DATA_IN:
01829     case SCSI_PHASE_MSG_IN:
01830       do_pci_write(R32(DNAD), scsi_data_ptr, 1, count);
01831       R32(DNAD) += count;
01832       break;
01833     }
01834 
01835     R8(SFBR) = *org_sdata_ptr;
01836     scsi_xfer_done(0);
01837     return;
01838   }
01839 }
01840 
01841 /* Execute one SCRIPTS I/O instruction
01842  * 
01843  * The I/O instructions perform common SCSI hardware sequences, like
01844  * Selection and reselection. The instruction format in
01845  * the DCMD and DBC register is as follows:
01846  *
01847  * \code
01848  * +---+-----+-+-+-+
01849  * |7 6|5 4 3|2|1|0| DCMD Register
01850  * +---+-----+-+-+-+
01851  *   |    |   | | +- 0: Select with ATN/:
01852  *   |    |   | |       Valid only for Select instruction. Assert ATN/ during 
01853  *   |    |   | |       selection
01854  *   |    |   | +- 1: Table Indirect Mode:
01855  *   |    |   |         0: All information is taken from the instruction,
01856  *   |    |   |            and the contents of the SCNTL3 and SXFER registers.
01857  *   |    |   |         1: The DSPS register contains a 24-bit signed offset
01858  *   |    |   |            that is added to the DSA register to get a pointer
01859  *   |    |   |            to a data structure that contains the destination
01860  *   |    |   |            ID, SCNTL3 bits, and SXFER bits. This structure 
01861  *   |    |   |            is 32 bits long and looks as follows:
01862  *   |    |   |                        +--------+--------+--------+--------+
01863  *   |    |   |            DSA+DSPS:   | SCNTL3 | ID     | SXFER  |        |
01864  *   |    |   |                        +--------+--------+--------+--------+
01865  *   |    |   +- 2: Relative Addrressing:
01866  *   |    |           0: The value in the DNAD register is an absolute address.
01867  *   |    |           1: The value in the DNAD register is a 24-bit signed
01868  *   |    |              displacement from the current DSP address.
01869  *   |    +- 3..5: Op Code
01870  *   +- 6..7 Instruction Type: 01 = I/O
01871  *
01872  * +-------+-------++--------+--+-+-++-+-+---+-+-----+
01873  * |       |19   16||        |10|9| || |6|   |3|     | DBC Register
01874  * +-------+-------++--------+--+-+-++-+-+---+-+-----+
01875  *             |              |  |      |     +- 3: Set/Clear ATN
01876  *             |              |  |      +- 6: Set/Clear ACK
01877  *             |              |  +- 9: Set/Clear Target Mode
01878  *             |              +- 10: Set/Clear Carry
01879  *             +- 16..19: Destination ID
01880  * \endcode
01881  *
01882  * The Opcode determines the actual instruction:
01883  * \code
01884  * +-----+-----------------+-------------+
01885  * | OPC | Initiator mode  | Target Mode |
01886  * +-----+-----------------+-------------+
01887  * | 000 | Select          | Reselect    |
01888  * | 001 | Wait Disconnect | Disconnect  |
01889  * | 010 | Wait Reselect   | Wait Select |
01890  * | 011 | Set             | Set         |
01891  * | 100 | Clear           | Clear       |
01892  * +-----+-----------------+-------------+
01893  * \endcode
01894  *
01895  * Select:
01896  *   - Arbitrate for the SCSI bus until arbitration is won.
01897  *   - If arbitration is won, try to select the destination ID
01898  *   - If the controller is selected or reselected before winning
01899  *     arbitration, jump to the address in the DNAD register.
01900  *   .
01901  *
01902  * Wait Disconnect:
01903  *   - Wait for the target to disconnect from the SCSI bus.
01904  *   .
01905  *
01906  * Wait Reselect:
01907  *   - If the controller is reselected, go to the next instruction.
01908  *   - If the controller is selected before being reselected, or if
01909  *     the CPU sets the SIGP flag, jump to the address in the DNAD 
01910  *     register
01911  *   .
01912  *
01913  * Set/Clear:
01914  *   - Set or Clear the flags whose Set/Clear bits are set in the
01915  *     instruction.
01916  *   .
01917  **/
01918 void CSym53C895::execute_io_op()
01919 {
01920   int   opcode = (R8(DCMD) >> 3) & 7;
01921   bool  relative = (R8(DCMD) >> 2) & 1;
01922   bool  table_indirect = (R8(DCMD) >> 1) & 1;
01923   bool  atn = (R8(DCMD) >> 0) & 1;
01924   int   destination = (GET_DBC() >> 16) & 0x0f;
01925   bool  sc_carry = (GET_DBC() >> 10) & 1;
01926   bool  sc_target = (GET_DBC() >> 9) & 1;
01927   bool  sc_ack = (GET_DBC() >> 6) & 1;
01928   bool  sc_atn = (GET_DBC() >> 3) & 1;
01929 
01930   R32(DNAD) = R32(DSPS);
01931 
01932   u32 dest_addr = R32(DNAD);
01933 
01934   if(relative)
01935     dest_addr = R32(DSP) + sext_u32_24(R32(DNAD));
01936 
01937 #if defined(DEBUG_SYM_SCRIPTS)
01938   printf("SYM: INS = I/O (opc %d, r %d, t %d, a %d, dest %d, sc %d%d%d%d\n",
01939          opcode, relative, table_indirect, atn, destination, sc_carry,
01940          sc_target, sc_ack, sc_atn);
01941 #endif
01942   if(table_indirect)
01943   {
01944     u32 io_addr = R32(DSA) + sext_u32_24(GET_DBC());
01945     io_addr &= ~3;      //810
01946 #if defined(DEBUG_SYM_SCRIPTS)
01947     printf("SYM: Reading table at DSA(%08x)+DBC(%08x) = %08x.\n",
01948            R32(DSA), sext_u32_24(GET_DBC()), io_addr);
01949 #endif
01950 
01951     u32 io_struc;
01952     do_pci_read(io_addr, &io_struc, 4, 1);
01953     destination = (io_struc >> 16) & 0x0f;
01954 #if defined(DEBUG_SYM_SCRIPTS)
01955     printf("SYM: table indirect. io_struct = %08x, new dest = %d.\n",
01956            io_struc, destination);
01957 #endif
01958   }
01959 
01960   switch(opcode)
01961   {
01962   case 0:
01963 #if defined(DEBUG_SYM_SCRIPTS)
01964     printf("SYM: %08x: SELECT %d.\n", R32(DSP) - 8, destination);
01965 #endif
01966     SET_DEST(destination);
01967     if(!scsi_arbitrate(0))
01968     {
01969 
01970       // scsi bus busy, try again next clock...
01971       printf("scsi bus busy...\n");
01972       R32(DSP) -= 8;
01973       return;
01974     }
01975 
01976     state.select_timeout = !scsi_select(0, destination);
01977     if(!state.select_timeout)   // select ok
01978       SB_R8(SCNTL2, SDU, true); // don't expect a disconnect
01979     return;
01980 
01981   case 1:
01982 #if defined(DEBUG_SYM_SCRIPTS)
01983     printf("SYM: %08x: WAIT DISCONNECT\n", R32(DSP) - 8);
01984 #endif
01985 
01986     // maybe we need to do more??
01987     scsi_free(0);
01988     return;
01989 
01990   case 2:
01991 #if defined(DEBUG_SYM_SCRIPTS)
01992     printf("SYM: %08x: WAIT RESELECT\n", R32(DSP) - 8);
01993 #endif
01994     if(TB_R8(ISTAT, SIGP))
01995     {
01996 #if defined(DEBUG_SYM_SCRIPTS)
01997       printf("SYM: SIGP set before wait reselect; jumping!\n");
01998 #endif
01999       R32(DSP) = dest_addr;
02000     }
02001     else
02002     {
02003       state.wait_reselect = true;
02004       state.wait_jump = dest_addr;
02005       state.executing = false;
02006     }
02007 
02008     return;
02009 
02010   case 3:
02011 #if defined(DEBUG_SYM_SCRIPTS)
02012     printf("SYM: %08x: SET %s%s%s%s\n", R32(DSP) - 8,
02013            sc_carry ? "carry " : "", sc_target ? "target " : "",
02014            sc_ack ? "ack " : "", sc_atn ? "atn " : "");
02015 #endif
02016     if(sc_ack)
02017       SB_R8(SOCL, ACK, true);
02018     if(sc_atn)
02019     {
02020       if(!TB_R8(SOCL, ATN))
02021       {
02022         SB_R8(SOCL, ATN, true);
02023 
02024         //printf("SET ATN.\n");
02025         //printf(">");
02026         //getchar();
02027       }
02028     }
02029 
02030     if(sc_target)
02031       SB_R8(SCNTL0, TRG, true);
02032     if(sc_carry)
02033       state.alu.carry = true;
02034     return;
02035 
02036   case 4:
02037 #if defined(DEBUG_SYM_SCRIPTS)
02038     printf("SYM: %08x: CLEAR %s%s%s%s\n", R32(DSP) - 8,
02039            sc_carry ? "carry " : "", sc_target ? "target " : "",
02040            sc_ack ? "ack " : "", sc_atn ? "atn " : "");
02041 #endif
02042     if(sc_ack)
02043       SB_R8(SOCL, ACK, false);
02044     if(sc_atn)
02045     {
02046       if(TB_R8(SOCL, ATN))
02047       {
02048         SB_R8(SOCL, ATN, false);
02049 
02050         //printf("RESET ATN.\n");
02051         //printf(">");
02052         //getchar();
02053       }
02054     }
02055 
02056     if(sc_target)
02057       SB_R8(SCNTL0, TRG, false);
02058     if(sc_carry)
02059       state.alu.carry = false;
02060     return;
02061 
02062     break;
02063   }
02064 }
02065 
02103 void CSym53C895::execute_rw_op()
02104 {
02105   int   opcode = (R8(DCMD) >> 3) & 7;
02106   int   oper = (R8(DCMD) >> 0) & 7;
02107   bool  use_data8_sfbr = (GET_DBC() >> 23) & 1;
02108   int   reg_address = ((GET_DBC() >> 16) & 0x7f); //| (GET_DBC() & 0x80); // manual is unclear about bit 7.
02109   u8    imm_data = (u8) (GET_DBC() >> 8) & 0xff;
02110   u8    op_data;
02111 
02112 #if defined(DEBUG_SYM_SCRIPTS)
02113   printf("SYM: INS = R/W (opc %d, oper %d, use %d, add %d, imm %02x\n",
02114          opcode, oper, use_data8_sfbr, reg_address, imm_data);
02115 #endif
02116   if(use_data8_sfbr)
02117     imm_data = R8(SFBR);
02118 
02119   if(oper != 0)
02120   {
02121     if(opcode == 5 || reg_address == 0x08)
02122     {
02123       op_data = R8(SFBR);
02124 #if defined(DEBUG_SYM_SCRIPTS)
02125       printf("SYM: %08x: sfbr (%02x) ", R32(DSP) - 8, op_data);
02126 #endif
02127     }
02128     else
02129     {
02130       op_data = (u8) ReadMem_Bar(0, 1, reg_address, 8);
02131 #if defined(DEBUG_SYM_SCRIPTS)
02132       printf("SYM: %08x: reg%02x (%02x) ", R32(DSP) - 8, reg_address,
02133              op_data);
02134 #endif
02135     }
02136   }
02137 
02138   u16 tmp16;
02139 
02140   switch(oper)
02141   {
02142   case 0:
02143     op_data = imm_data;
02144 #if defined(DEBUG_SYM_SCRIPTS)
02145     printf("SYM: %08x: %02x ", R32(DSP) - 8, imm_data);
02146 #endif
02147     break;
02148 
02149   case 1:
02150     tmp16 = (op_data << 1) + (state.alu.carry ? 1 : 0);
02151     state.alu.carry = (tmp16 >> 8) & 1;
02152     op_data = tmp16 & 0xff;
02153 #if defined(DEBUG_SYM_SCRIPTS)
02154     printf("<< 1 = %02x ", op_data);
02155 #endif
02156     break;
02157 
02158   case 2:
02159     op_data |= imm_data;
02160 #if defined(DEBUG_SYM_SCRIPTS)
02161     printf("| %02x = %02x ", imm_data, op_data);
02162 #endif
02163     break;
02164 
02165   case 3:
02166     op_data ^= imm_data;
02167 #if defined(DEBUG_SYM_SCRIPTS)
02168     printf("^ %02x = %02x ", imm_data, op_data);
02169 #endif
02170     break;
02171 
02172   case 4:
02173     op_data &= imm_data;
02174 #if defined(DEBUG_SYM_SCRIPTS)
02175     printf("& %02x = %02x ", imm_data, op_data);
02176 #endif
02177     break;
02178 
02179   case 5:
02180     tmp16 = (op_data >> 1) + (state.alu.carry ? 0x80 : 0x00);
02181     state.alu.carry = op_data & 1;
02182     op_data = tmp16 & 0xff;
02183 #if defined(DEBUG_SYM_SCRIPTS)
02184     printf(">> 1 = %02x ", op_data);
02185 #endif
02186     break;
02187 
02188   case 6:
02189     tmp16 = op_data + imm_data;
02190     state.alu.carry = (tmp16 > 0xff);
02191     op_data = tmp16 & 0xff;
02192 #if defined(DEBUG_SYM_SCRIPTS)
02193     printf("+ %02x = %02x (carry %d) ", imm_data, op_data, state.alu.carry);
02194 #endif
02195     break;
02196 
02197   case 7:
02198     tmp16 = op_data + imm_data + (state.alu.carry ? 1 : 0);
02199     state.alu.carry = (tmp16 > 0xff);
02200     op_data = tmp16 & 0xff;
02201 #if defined(DEBUG_SYM_SCRIPTS)
02202     printf("+ %02x (w/carry) = %02x (carry %d) ", imm_data, op_data,
02203            state.alu.carry);
02204 #endif
02205     break;
02206   }
02207 
02208   if(opcode == 6 || reg_address == 0x08)
02209   {
02210 #if defined(DEBUG_SYM_SCRIPTS)
02211     printf("-> sfbr.\n");
02212 #endif
02213     R8(SFBR) = op_data;
02214   }
02215   else
02216   {
02217 #if defined(DEBUG_SYM_SCRIPTS)
02218     printf("-> reg%02x.\n", reg_address);
02219 #endif
02220     WriteMem_Bar(0, 1, reg_address, 8, op_data);
02221   }
02222 }
02223 
02298 void CSym53C895::execute_tc_op()
02299 {
02300   int   opcode = (R8(DCMD) >> 3) & 7;
02301   int   scsi_phase = (R8(DCMD) >> 0) & 7;
02302   bool  relative = (GET_DBC() >> 23) & 1;
02303   bool  carry_test = (GET_DBC() >> 21) & 1;
02304   bool  interrupt_fly = (GET_DBC() >> 20) & 1;
02305   bool  jump_if = (GET_DBC() >> 19) & 1;
02306   bool  cmp_data = (GET_DBC() >> 18) & 1;
02307   bool  cmp_phase = (GET_DBC() >> 17) & 1;
02308   int   cmp_mask = (GET_DBC() >> 8) & 0xff;
02309   int   cmp_dat = (GET_DBC() >> 0) & 0xff;
02310   u32   dest_addr;
02311 
02312   // wait_valid can be safely ignored, phases are always valid in this ideal world...
02313   // bool wait_valid = (GET_DBC()>>16) & 1;
02314 
02315   // We'll keep modifying this variable until we know what the result of the comparisons is.
02316   bool  do_it;
02317 
02318   // Relative jump or not? (no effect on Return or Interrupt)
02319   if(relative)
02320     dest_addr = R32(DSP) + sext_u32_24(R32(DSPS));
02321   else
02322     dest_addr = R32(DSPS);
02323 
02324 #if defined(DEBUG_SYM_SCRIPTS)
02325   printf("SYM: %08x: if (", R32(DSP) - 8);
02326 #endif
02327   if(carry_test)
02328   {
02329     // All we need to check is the CARRY flag
02330 #if defined(DEBUG_SYM_SCRIPTS)
02331     printf("(%scarry)", jump_if ? "" : "!");
02332 #endif
02333     do_it = (state.alu.carry == jump_if);
02334   }
02335   else if(cmp_data || cmp_phase)
02336   {
02337     // We need to compare data and/or phase
02338     do_it = true;
02339     if(cmp_data)
02340     {
02341       // compare data
02342 #if defined(DEBUG_SYM_SCRIPTS)
02343       printf("((data & 0x%02x) %s 0x%02x)", (~cmp_mask) & 0xff,
02344              jump_if ? "==" : "!=", cmp_dat &~cmp_mask);
02345 #endif
02346       if(((R8(SFBR) &~cmp_mask) == (cmp_dat &~cmp_mask)) != jump_if)
02347         do_it = false;
02348 #if defined(DEBUG_SYM_SCRIPTS)
02349       if(cmp_phase)
02350         printf(" && ");
02351 #endif
02352     }
02353 
02354     if(cmp_phase)
02355     {
02356       // Compare phase
02357 #if defined(DEBUG_SYM_SCRIPTS)
02358       printf("(phase %s %d)", jump_if ? "==" : "!=", scsi_phase);
02359 #endif
02360       if((check_phase(scsi_phase)>0) != jump_if)
02361         do_it = false;
02362     }
02363   }
02364   else
02365   {
02366 
02367     // no comparison
02368     do_it = jump_if;
02369   }
02370 
02371 #if defined(DEBUG_SYM_SCRIPTS)
02372   printf(") ");
02373 #endif
02374   switch(opcode)
02375   {
02376   case 0:
02377 #if defined(DEBUG_SYM_SCRIPTS)
02378     printf("jump %x\n", R32(DSPS));
02379 #endif
02380     if(do_it)
02381     {
02382 #if defined(DEBUG_SYM_SCRIPTS)
02383       printf("SYM: Jumping %08x...\n", dest_addr);
02384 #endif
02385       R32(DSP) = dest_addr;
02386     }
02387 
02388     return;
02389     break;
02390 
02391   case 1:
02392 #if defined(DEBUG_SYM_SCRIPTS)
02393     printf("call %d\n", R32(DSPS));
02394 #endif
02395     if(do_it)
02396     {
02397 #if defined(DEBUG_SYM_SCRIPTS)
02398       printf("SYM: Calling %08x...\n", dest_addr);
02399 #endif
02400       R32(TEMP) = R32(DSP);
02401       R32(DSP) = dest_addr;
02402     }
02403 
02404     return;
02405     break;
02406 
02407   case 2:
02408 #if defined(DEBUG_SYM_SCRIPTS)
02409     printf("return %d\n", R32(DSPS));
02410 #endif
02411     if(do_it)
02412     {
02413 #if defined(DEBUG_SYM_SCRIPTS)
02414       printf("SYM: Returning %08x...\n", R32(TEMP));
02415 #endif
02416       R32(DSP) = R32(TEMP);
02417     }
02418 
02419     return;
02420     break;
02421 
02422   case 3:
02423 #if defined(DEBUG_SYM_SCRIPTS)
02424     printf("interrupt%s.\n", interrupt_fly ? " on the fly" : "");
02425 #endif
02426     if(do_it)
02427     {
02428 #if defined(DEBUG_SYM_SCRIPTS)
02429       printf("SYM: Interrupt with vector %x...\n", R32(DSPS));
02430 #endif
02431       if(interrupt_fly)
02432         RAISE(ISTAT, INTF);
02433       else
02434         RAISE(DSTAT, SIR);
02435     }
02436 
02437     return;
02438     break;
02439 
02440   default:
02441     FAILURE_1(NotImplemented,
02442               "SYM: Transfer Control Instruction with opcode %d is RESERVED.\n",
02443               opcode);
02444   }
02445 }
02446 
02478 void CSym53C895::execute_ls_op()
02479 {
02480   bool  is_load = (R8(DCMD) >> 0) & 1;
02481   bool  no_flush = (R8(DCMD) >> 1) & 1;
02482   bool  dsa_relative = (R8(DCMD) >> 4) & 1;
02483   int   regaddr = (GET_DBC() >> 16) & 0x7f;
02484   int   byte_count = (GET_DBC() >> 0) & 7;
02485   u32   memaddr;
02486 
02487   // Relative Addressing
02488   if(dsa_relative)
02489     memaddr = R32(DSA) + sext_u32_24(R32(DSPS));
02490   else
02491     memaddr = R32(DSPS);
02492 
02493 #if defined(DEBUG_SYM_SCRIPTS)
02494   printf("SYM: dsa_rel: %d, DSA: %04x, DSPS: %04x, mem %04x.\n",
02495          dsa_relative, R32(DSA), R32(DSPS), memaddr);
02496 #endif
02497   if(is_load)
02498   {
02499 #if defined(DEBUG_SYM_SCRIPTS)
02500     printf("SYM: %08x: Load reg%02x", R32(DSP) - 8, regaddr);
02501     if(byte_count > 1)
02502       printf("..%02x", regaddr + byte_count - 1);
02503     printf("from %x.\n", memaddr);
02504 #endif
02505     // Perform Load Operation
02506     for(int i = 0; i < byte_count; i++)
02507     {
02508       u8  dat;
02509       do_pci_read(memaddr + i, &dat, 1, 1);
02510 #if defined(DEBUG_SYM_SCRIPTS)
02511       printf("SYM: %02x -> reg%02x\n", dat, regaddr + i);
02512 #endif
02513       WriteMem_Bar(0, 1, regaddr + i, 8, dat);
02514     }
02515   }
02516   else
02517   {
02518 #if defined(DEBUG_SYM_SCRIPTS)
02519     printf("SYM: %08x: Store reg%02x", R32(DSP) - 8, regaddr);
02520     if(byte_count > 1)
02521       printf("..%02x", regaddr + byte_count - 1);
02522     printf("to %x.\n", memaddr);
02523 #endif
02524     // Perform Store Operation
02525     for(int i = 0; i < byte_count; i++)
02526     {
02527       u8  dat = (u8) ReadMem_Bar(0, 1, regaddr + i, 8);
02528 #if defined(DEBUG_SYM_SCRIPTS)
02529       printf("SYM: %02x <- reg%02x\n", dat, regaddr + i);
02530 #endif
02531       do_pci_write(memaddr + i, &dat, 1, 1);
02532     }
02533   }
02534 }
02535 
02558 void CSym53C895::execute_mm_op()
02559 {
02560   u32 temp_shadow;
02561   do_pci_read(R32(DSP), &temp_shadow, 4, 1);
02562   R32(DSP) += 4;
02563 
02564 #if defined(DEBUG_SYM_SCRIPTS)
02565   printf("SYM: %08x: Memory Move %06x bytes from %08x to %08x.\n",
02566          R32(DSP) - 12, GET_DBC(), R32(DSPS), temp_shadow);
02567 #endif
02568 
02569   // To speed things up, we set up a buffer and read all data
02570   // at once, followed by writing all data at once.
02571   void*   buf = malloc(GET_DBC());
02572   do_pci_read(R32(DSPS), buf, 1, GET_DBC());
02573   do_pci_write(temp_shadow, buf, 1, GET_DBC());
02574   free(buf);
02575   return;
02576 }
02577 
02597 void CSym53C895::execute()
02598 {
02599   int optype;
02600   int opcode;
02601   bool is_load_store;
02602 
02603 #if defined(DEBUG_SYM_SCRIPTS)
02604       printf("SYM: INS @ %x   \n",R32(DSP));
02605 #endif
02606 
02607   // Read 2 DWORDS into the DCMD, DBC and DSPS registers.
02608   do_pci_read(R32(DSP), &R32(DBC), 4, 1);
02609   do_pci_read(R32(DSP) + 4, &R32(DSPS), 4, 1);
02610 
02611   // Increase DSP to point to the next instruction
02612   R32(DSP) += 8;
02613 
02614 #if defined(DEBUG_SYM_SCRIPTS)
02615   printf("SYM: INS = %x, %x, %x   \n", R8(DCMD), GET_DBC(), R32(DSPS));
02616 #endif
02617   /* The two most significant bits of the DCMD register determine the operation
02618    * type. These are:
02619    *   00: Block Move
02620    *   01: I/O or R/W
02621    *   10: Transfer Control
02622    *   11: Memory Move or Load And Store
02623    */
02624   optype = (R8(DCMD) >> 6) & 3;
02625   switch(optype)
02626   {
02627   case 0:
02628     execute_bm_op();
02629     break;
02630 
02631   case 1:
02632     opcode = (R8(DCMD) >> 3) & 7;
02633     if(opcode < 5)
02634       execute_io_op();
02635     else
02636       execute_rw_op();
02637     break;
02638 
02639   case 2:
02640     execute_tc_op();
02641     break;
02642 
02643   case 3:
02644     is_load_store = (R8(DCMD) >> 5) & 1;
02645     if(is_load_store)
02646       execute_ls_op();
02647     else
02648       execute_mm_op();
02649     break;
02650   }
02651 
02652   // single step mode
02653   if(TB_R8(DCNTL, SSM))
02654   {
02655 #if defined(DEBUG_SYM_SCRIPTS)
02656     printf("SYM: Single step...\n");
02657 #endif
02658     RAISE(DSTAT, SSI);
02659   }
02660 }
02661 
02690 void CSym53C895::set_interrupt(int reg, u8 interrupt)
02691 {
02692   //printf("set interrupt %02x, %02x.\n",reg,interrupt);
02693   switch(reg)
02694   {
02695   case R_DSTAT:
02696     if(TB_R8(ISTAT, DIP) || TB_R8(ISTAT, SIP))
02697     {
02698       state.dstat_stack |= interrupt;
02699 
02700       //printf("DSTAT stacked.\n");
02701     }
02702     else
02703     {
02704       R8(DSTAT) |= interrupt;
02705 
02706       //printf("DSTAT.\n");
02707     }
02708     break;
02709 
02710   case R_SIST0:
02711     if(TB_R8(ISTAT, DIP) || TB_R8(ISTAT, SIP))
02712     {
02713       state.sist0_stack |= interrupt;
02714 
02715       //printf("SIST0 stacked.\n");
02716     }
02717     else
02718     {
02719       R8(SIST0) |= interrupt;
02720 
02721       //printf("SIST0.\n");
02722     }
02723     break;
02724 
02725   case R_SIST1:
02726     if(TB_R8(ISTAT, DIP) || TB_R8(ISTAT, SIP))
02727     {
02728       state.sist1_stack |= interrupt;
02729 
02730       //printf("SIST1 stacked.\n");
02731     }
02732     else
02733     {
02734       R8(SIST1) |= interrupt;
02735 
02736       //printf("SIST1.\n");
02737     }
02738     break;
02739 
02740   case R_ISTAT:
02741 
02742     //printf("ISTAT.\n");
02743     R8(ISTAT) |= interrupt;
02744     break;
02745 
02746   default:
02747     FAILURE_1(NotImplemented, "set_interrupt reg %02x!!\n", reg);
02748   }
02749 
02750   //printf("--> eval int\n");
02751   eval_interrupts();
02752 
02753   //printf("<-- eval_int\n");
02754 }
02755 
02761 void CSym53C895::eval_interrupts()
02762 {
02763   // will_assert: when this boolean value is true at the end of this function, an
02764   // interrupt will be signalled to the system.
02765   bool  will_assert = false;
02766   
02767   // will_halt: when this boolean value is true at the end of this function,
02768   // program execution will be halted. (fatal interrupt)
02769   bool  will_halt = false;
02770 
02771   // Check current interrupt status. If no interrupt is active, move interrupt
02772   // flags from the interrupt stack down.
02773   //
02774   // (When an interrupt is signalled, but another interrupt bit is already active,
02775   // the interrupt doesn't go to the interrupt register, but to the interrupt 
02776   // stack. The interrupt stack, however, doesn't keep track of the order in which
02777   // interrupts come in, so when the interrupt stack is moved down into the 
02778   // interrupt registers, multiple interrupt bits may become active.)
02779   if(!R8(SIST0) && !R8(SIST1) && !R8(DSTAT))
02780   {
02781     R8(SIST0) |= state.sist0_stack;
02782     R8(SIST1) |= state.sist1_stack;
02783     R8(DSTAT) |= state.dstat_stack;
02784     state.sist0_stack = 0;
02785     state.sist1_stack = 0;
02786     state.dstat_stack = 0;
02787   }
02788 
02789   // Check for DMA interrupts.
02790   if(R8(DSTAT) & DSTAT_FATAL)
02791   {
02792     // DMA interrupt conditions always halt execution (always fatal)
02793     will_halt = true;
02794 
02795     //printf("  will halt(DSTAT).\n");
02796 
02797     // Set the DMA interrupt pending bit.
02798     SB_R8(ISTAT, DIP, true);
02799 
02800     // If the interrupt is also enabled in the DIEN register, it will
02801     // be signalled to the system.
02802     if(R8(DSTAT) & R8(DIEN) & DSTAT_FATAL)
02803     {
02804       will_assert = true;
02805 
02806       //printf("  will assert(DSTAT).\n");
02807     }
02808   }
02809   else
02810   {
02811     // Reset the DMA interrupt pending bit. (It may still be set).
02812     SB_R8(ISTAT, DIP, false);
02813   }
02814 
02815   // Check for SCSI engine interrupts
02816   if(R8(SIST0) || R8(SIST1))
02817   {
02818     // Set the SCSI interrupt pending bit.
02819     SB_R8(ISTAT, SIP, true);
02820 
02821     //Check if the interrupt is either fatal, or enabled.
02822     if((R8(SIST0) & (SIST0_FATAL | R8(SIEN0)))
02823      || (R8(SIST1) & (SIST1_FATAL | R8(SIEN1))))
02824     {
02825       // In either case, stop execution.
02826       will_halt = true;
02827 
02828       //printf("  will halt(SIST).\n");
02829 
02830       // If the interrupt is enabled, signal it to the system.
02831       if((R8(SIST0) & R8(SIEN0)) || (R8(SIST1) & R8(SIEN1)))
02832       {
02833         will_assert = true;
02834 
02835         //printf("  will assert(SIST).\n");
02836       }
02837     }
02838   }
02839   else
02840   {
02841     // Reset the SCSI interrupt pending bit (It may still be set).
02842     SB_R8(ISTAT, SIP, false);
02843   }
02844 
02845   // Check the interrupt on the fly bit.
02846   if(TB_R8(ISTAT, INTF))
02847   {
02848     // Signal this to the system
02849     will_assert = true;
02850 
02851     //printf("  will assert(INTF).\n");
02852   }
02853 
02854   // If interrupts are disabled, don't signal any interrupt to the system.
02855   if(TB_R8(DCNTL, IRQD))
02856   {
02857     will_assert = false;
02858 
02859     //printf("  won't assert(IRQD).\n");
02860   }
02861 
02862   // Halt execution if will_halt is true.
02863   if(will_halt)
02864     state.executing = false;
02865 
02866   // Assert or de-assert the interrupt line as needed
02867   if(will_assert != state.irq_asserted)
02868   {
02869 
02870     //printf("  doing...%d\n",will_assert);
02871     do_pci_interrupt(0, will_assert);
02872     state.irq_asserted = will_assert;
02873   }
02874 }

SourceForge.net Logo
Project space on SourceForge.net