Disk.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 
00124 #include "StdAfx.h"
00125 #include "Disk.h"
00126 
00130 CDisk::CDisk(CConfigurator*  cfg, CSystem*  sys, CDiskController*  ctrl,
00131              int idebus, int idedev) : CSystemComponent(cfg, sys)
00132 {
00133   char*   a;
00134   char*   b;
00135   char*   c;
00136   char*   d;
00137 
00138   myCfg = cfg;
00139   myCtrl = ctrl;
00140   myBus = idebus;
00141   myDev = idedev;
00142   atapi_mode = false;
00143 
00144   a = myCfg->get_myName();
00145   b = myCfg->get_myValue();
00146   c = myCfg->get_myParent()->get_myName();
00147   d = myCfg->get_myParent()->get_myValue();
00148 
00149   free(devid_string); // we override the default to include the controller.
00150   CHECK_ALLOCATION(devid_string = (char*) malloc(
00151                      strlen(a) + strlen(b) + strlen(c) + strlen(d) + 6));
00152   sprintf(devid_string, "%s(%s).%s(%s)", c, d, a, b);
00153 
00154   serial_number = myCfg->get_text_value("serial_num", "ES40EM00000");
00155   revision_number = myCfg->get_text_value("rev_num", "0.0");
00156   read_only = myCfg->get_bool_value("read_only");
00157   is_cdrom = myCfg->get_bool_value("cdrom");
00158 
00159   state.block_size = is_cdrom ? 2048 : 512;
00160   state.scsi.sense.available = false;
00161 
00162   myCtrl->register_disk(this, myBus, myDev);
00163 }
00164 
00168 CDisk::~CDisk(void)
00169 {
00170   free(devid_string);
00171 }
00172 
00176 void CDisk::calc_cylinders()
00177 {
00178   cylinders = byte_size / state.block_size / sectors / heads;
00179 
00180   off_t_large chs_size = sectors * cylinders * heads * state.block_size;
00181   if(chs_size < byte_size)
00182     cylinders++;
00183 }
00184 
00191 void CDisk::scsi_select_me(int bus)
00192 {
00193   state.scsi.msgo.written = 0;
00194   state.scsi.msgi.available = 0;
00195   state.scsi.msgi.read = 0;
00196   state.scsi.cmd.written = 0;
00197   state.scsi.dati.available = 0;
00198   state.scsi.dati.read = 0;
00199   state.scsi.dato.expected = 0;
00200   state.scsi.dato.written = 0;
00201   state.scsi.stat.available = 0;
00202   state.scsi.stat.read = 0;
00203   state.scsi.lun_selected = false;
00204 
00205   //state.scsi.disconnect_priv = false;
00206   //state.scsi.will_disconnect = false;
00207   //state.scsi.disconnected = false;
00208   if(atapi_mode)
00209     scsi_set_phase(bus, SCSI_PHASE_COMMAND);
00210   else
00211     scsi_set_phase(bus, SCSI_PHASE_MSG_OUT);
00212 }
00213 
00214 static u32  disk_magic1 = 0xD15D15D1;
00215 static u32  disk_magic2 = 0x15D15D5;
00216 
00220 int CDisk::SaveState(FILE* f)
00221 {
00222   long  ss = sizeof(state);
00223 
00224   fwrite(&disk_magic1, sizeof(u32), 1, f);
00225   fwrite(&ss, sizeof(long), 1, f);
00226   fwrite(&state, sizeof(state), 1, f);
00227   fwrite(&disk_magic2, sizeof(u32), 1, f);
00228   printf("%s: %d bytes saved.\n", devid_string, (int) ss);
00229   return 0;
00230 }
00231 
00235 int CDisk::RestoreState(FILE* f)
00236 {
00237   long    ss;
00238   u32     m1;
00239   u32     m2;
00240   size_t  r;
00241 
00242   r = fread(&m1, sizeof(u32), 1, f);
00243   if(r != 1)
00244   {
00245     printf("%s: unexpected end of file!\n", devid_string);
00246     return -1;
00247   }
00248 
00249   if(m1 != disk_magic1)
00250   {
00251     printf("%s: MAGIC 1 does not match!\n", devid_string);
00252     return -1;
00253   }
00254 
00255   fread(&ss, sizeof(long), 1, f);
00256   if(r != 1)
00257   {
00258     printf("%s: unexpected end of file!\n", devid_string);
00259     return -1;
00260   }
00261 
00262   if(ss != sizeof(state))
00263   {
00264     printf("%s: STRUCT SIZE does not match!\n", devid_string);
00265     return -1;
00266   }
00267 
00268   fread(&state, sizeof(state), 1, f);
00269   if(r != 1)
00270   {
00271     printf("%s: unexpected end of file!\n", devid_string);
00272     return -1;
00273   }
00274 
00275   r = fread(&m2, sizeof(u32), 1, f);
00276   if(r != 1)
00277   {
00278     printf("%s: unexpected end of file!\n", devid_string);
00279     return -1;
00280   }
00281 
00282   if(m2 != disk_magic2)
00283   {
00284     printf("%s: MAGIC 1 does not match!\n", devid_string);
00285     return -1;
00286   }
00287 
00288   //calc_cylinders(); // state.block_size may have changed.
00289   determine_layout();
00290 
00291   printf("%s: %d bytes restored.\n", devid_string, (int) ss);
00292   return 0;
00293 }
00294 
00305 size_t CDisk::scsi_expected_xfer_me(int bus)
00306 {
00307   switch(scsi_get_phase(0))
00308   {
00309   case SCSI_PHASE_DATA_OUT:
00310     return state.scsi.dato.expected - state.scsi.dato.written;
00311 
00312   case SCSI_PHASE_DATA_IN:
00313     return state.scsi.dati.available - state.scsi.dati.read;
00314 
00315   case SCSI_PHASE_COMMAND:
00316     return 256 - state.scsi.cmd.written;
00317 
00318   case SCSI_PHASE_STATUS:
00319     return state.scsi.stat.available - state.scsi.stat.read;
00320 
00321   case SCSI_PHASE_MSG_OUT:
00322     return 256 - state.scsi.msgo.written;
00323 
00324   case SCSI_PHASE_MSG_IN:
00325     return state.scsi.msgi.available - state.scsi.msgi.read;
00326 
00327   default:
00328     FAILURE_2(IllegalState, "%s: transfer requested in phase %d\n",
00329               devid_string, scsi_get_phase(0));
00330   }
00331 }
00332 
00342 void* CDisk::scsi_xfer_ptr_me(int bus, size_t bytes)
00343 {
00344   void*   res = 0;
00345 
00346   switch(scsi_get_phase(0))
00347   {
00348   case SCSI_PHASE_DATA_OUT:
00349     res = &(state.scsi.dato.data[state.scsi.dato.written]);
00350     state.scsi.dato.written += bytes;
00351     break;
00352 
00353   case SCSI_PHASE_DATA_IN:
00354     res = &(state.scsi.dati.data[state.scsi.dati.read]);
00355     state.scsi.dati.read += bytes;
00356     break;
00357 
00358   case SCSI_PHASE_COMMAND:
00359     res = &(state.scsi.cmd.data[state.scsi.cmd.written]);
00360     state.scsi.cmd.written += bytes;
00361     break;
00362 
00363   case SCSI_PHASE_STATUS:
00364     res = &(state.scsi.stat.data[state.scsi.stat.read]);
00365     state.scsi.stat.read += bytes;
00366     break;
00367 
00368   case SCSI_PHASE_MSG_OUT:
00369     res = &(state.scsi.msgo.data[state.scsi.msgo.written]);
00370     state.scsi.msgo.written += bytes;
00371     break;
00372 
00373   case SCSI_PHASE_MSG_IN:
00374 
00375     //if (PT.reselected)
00376     //{
00377     //  retval = 0x80; // identify
00378     //  break;
00379     //}
00380     //if (PT.disconnected)
00381     //{
00382     //  if (!PT.dati_ptr)
00383     //    retval = 0x04; // disconnect
00384     //  else
00385     //  {
00386     //    if (state.scsi.msgi.read==0)
00387     //    {
00388     //      retval = 0x02; // save data pointer
00389     //      state.scsi.msgi.read=1;
00390     //    }
00391     //    else if (state.scsi.msgi.read==1)
00392     //    {
00393     //      retval = 0x04; // disconnect
00394     //      state.scsi.msgi.read=0;
00395     //    }
00396     //  }
00397     //  break;
00398     //}
00399     res = &(state.scsi.msgi.data[state.scsi.msgi.read]);
00400     state.scsi.msgi.read += bytes;
00401     break;
00402 
00403   default:
00404     FAILURE_2(IllegalState, "%s: transfer requested in phase %d\n",
00405               devid_string, scsi_get_phase(0));
00406   }
00407 
00408   return res;
00409 }
00410 
00422 void CDisk::scsi_xfer_done_me(int bus)
00423 {
00424   int res;
00425   int newphase = scsi_get_phase(0);
00426 
00427   switch(scsi_get_phase(0))
00428   {
00429   case SCSI_PHASE_DATA_OUT:
00430     if(state.scsi.dato.written < state.scsi.dato.expected)
00431       break;
00432 
00433     res = do_scsi_command();
00434     if(res == 2)
00435       FAILURE(IllegalState, "do_command returned 2 after DATA OUT phase");
00436 
00437     if(state.scsi.dati.available)
00438       newphase = SCSI_PHASE_DATA_IN;
00439     else
00440       newphase = SCSI_PHASE_STATUS;
00441     break;
00442 
00443   case SCSI_PHASE_DATA_IN:
00444     if(state.scsi.dati.read < state.scsi.dati.available)
00445       break;
00446 
00447     newphase = SCSI_PHASE_STATUS;
00448     break;
00449 
00450   case SCSI_PHASE_COMMAND:
00451     res = do_scsi_command();
00452     if(res == 2)
00453       newphase = SCSI_PHASE_DATA_OUT;
00454     else if(state.scsi.dati.available)
00455       newphase = SCSI_PHASE_DATA_IN;
00456     else
00457       newphase = SCSI_PHASE_STATUS;
00458     break;
00459 
00460   case SCSI_PHASE_STATUS:
00461     if(state.scsi.stat.read < state.scsi.stat.available)
00462       break;
00463 
00464     if(atapi_mode)
00465     {
00466       scsi_free(0);
00467       return;
00468     }
00469 
00470     newphase = SCSI_PHASE_MSG_IN;
00471     break;
00472 
00473   case SCSI_PHASE_MSG_OUT:
00474     newphase = do_scsi_message();       // command
00475     break;
00476 
00477   case SCSI_PHASE_MSG_IN:
00478 
00479     //if (state.scsi.reselected)
00480     //{
00481     //  state.scsi.reselected = false;
00482     //  newphase = state.scsi.disconnect_phase;
00483     //}
00484     //else if (state.scsi.disconnected)
00485     //{
00486     //  if (!state.scsi.msgi.read)
00487     //    newphase = -1;
00488     //}
00489     if(state.scsi.msgi.read < state.scsi.msgi.available)
00490       break;
00491 
00492     if(state.scsi.cmd.written)
00493     {
00494       scsi_free(0);
00495       return;
00496     }
00497     else
00498       newphase = SCSI_PHASE_COMMAND;
00499     break;
00500 
00501   default:
00502     FAILURE_2(IllegalState, "%s: transfer requested in phase %d\n",
00503               devid_string, scsi_get_phase(0));
00504   }
00505 
00506   // if data in and can disconnect...
00507   //if (state.phase!=7 && newphase==1 && PT.will_disconnect && !PT.disconnected)
00508   //{
00509   //  printf("%s: Disconnecting now...\n",devid_string);
00510   //  PT.disconnected = true;
00511   //  PT.disconnect_phase = newphase;
00512   //  newphase = 7; // msg in
00513   //}
00514   if(newphase != scsi_get_phase(0))
00515   {
00516 
00517     //    if (newphase==-1)
00518     //    {
00519     //      printf("%s: Disconnect. Timer started!\n",devid_string);
00520     //      // disconnect. generate interrupt?
00521     //      state.disconnected = 20;
00522     //    }
00523     scsi_set_phase(0, newphase);
00524   }
00525 
00526   //getchar();
00527 }
00528 
00529 // SCSI commands:
00530 #define SCSICMD_TEST_UNIT_READY       0x00
00531 #define SCSICMD_REQUEST_SENSE         0x03
00532 #define SCSICMD_INQUIRY               0x12
00533 
00534 #define SCSICMD_READ                  0x08
00535 #define SCSICMD_READ_10               0x28
00536 #define SCSICMD_READ_12               0xA8
00537 #define SCSICMD_READ_16               0x88
00538 #define SCSICMD_READ_32               0x7F
00539 #define SCSICMD_READ_LONG             0x3E
00540 #define SCSICMD_READ_CD               0xBE
00541 
00542 #define SCSICMD_WRITE                 0x0A
00543 #define SCSICMD_WRITE_10              0x2A
00544 #define SCSICMD_WRITE_12              0xAA
00545 #define SCSICMD_WRITE_LONG            0x3F
00546 
00547 #define SCSICMD_MODE_SELECT           0x15
00548 #define SCSICMD_MODE_SENSE            0x1a
00549 #define SCSICMD_START_STOP_UNIT       0x1b
00550 #define SCSICMD_PREVENT_ALLOW_REMOVE  0x1e
00551 #define SCSICMD_MODE_SENSE_10         0x5a
00552 
00553 #define SCSICMD_SYNCHRONIZE_CACHE     0x35
00554 
00555 //  SCSI block device commands:
00556 #define SCSIBLOCKCMD_READ_CAPACITY  0x25
00557 
00558 //  SCSI CD-ROM commands:
00559 #define SCSICDROM_READ_SUBCHANNEL 0x42
00560 #define SCSICDROM_READ_TOC        0x43
00561 
00562 // SCSI CD-R/RW commands:
00563 #define SCSICDRRW_FORMAT          0x04
00564 #define SCSICDRRW_READ_DISC_INFO  0x51
00565 #define SCSICDRRW_READ_TRACK_INFO 0x52
00566 #define SCSICDRRW_RESERVE_TRACK   0x53
00567 #define SCSICDRRW_SEND_OPC_INFO   0x54
00568 #define SCSICDRRW_REPAIR_TRACK    0x58
00569 #define SCSICDRRW_READ_MASTER_CUE 0x59
00570 #define SCSICDRRW_CLOSE_TRACK     0x5b
00571 #define SCSICDRRW_READ_BUFFER_CAP 0x5c
00572 #define SCSICDRRW_SEND_CUE_SHEET  0x5d
00573 #define SCSICDRRW_BLANK           0xa1
00574 
00575 //  SCSI tape commands:
00576 #define SCSICMD_REWIND            0x01
00577 #define SCSICMD_READ_BLOCK_LIMITS 0x05
00578 #define SCSICMD_SPACE             0x11
00579 
00580 // SCSI mode pages:
00581 #define SCSIMP_VENDOR               0x00
00582 #define SCSIMP_READ_WRITE_ERRREC    0x01
00583 #define SCSIMP_DISCONNECT_RECONNECT 0x02
00584 #define SCSIMP_FORMAT_PARAMS        0x03
00585 #define SCSIMP_RIGID_GEOMETRY       0x04
00586 #define SCSIMP_FLEX_PARAMS          0x05
00587 #define SCSIMP_CACHING              0x08
00588 #define SCSIMP_CDROM_CAP            0x2A
00589 
00590 #define SCSI_OK                     0
00591 #define SCSI_ILL_CMD                - 1 /* illegal command */
00592 #define SCSI_LBA_RANGE              - 2 /* LBA out of range */
00593 #define SCSI_TOO_BIG                - 3 /* Too big for buffer */
00594 
00595 void CDisk::do_scsi_error(int errcode)
00596 {
00597   state.scsi.stat.available = 1;
00598   state.scsi.stat.data[0] = 0;
00599   state.scsi.stat.read = 0;
00600   state.scsi.msgi.available = 1;
00601   state.scsi.msgi.data[0] = 0;
00602   state.scsi.msgi.read = 0;
00603 
00604   if(errcode == SCSI_OK)
00605   {
00606 #if defined(DEBUG_SCSI)
00607     printf("%s: Command returns OK status.\n", devid_string);
00608 #endif
00609     return;
00610   }
00611 
00612   state.scsi.stat.data[0] = 0x02;       // check sense
00613   state.scsi.sense.data[0] = 0xf0;      // error code
00614   state.scsi.sense.data[1] = 0x00;      // segment number
00615   state.scsi.sense.data[3] = 0x00;      // info
00616   state.scsi.sense.data[4] = 0x00;
00617   state.scsi.sense.data[5] = 0x00;
00618   state.scsi.sense.data[6] = 0x00;
00619   state.scsi.sense.data[7] = 10;        // additional sense length
00620   state.scsi.sense.data[8] = 0x00;      // command specific
00621   state.scsi.sense.data[9] = 0x00;
00622   state.scsi.sense.data[10] = 0x00;
00623   state.scsi.sense.data[11] = 0x00;
00624   state.scsi.sense.data[14] = 0x00;     // FRU code
00625   state.scsi.sense.data[15] = 0x00;     // sense key specific
00626   state.scsi.sense.data[16] = 0x00;
00627   state.scsi.sense.data[17] = 0x00;
00628   state.scsi.sense.available = 18;
00629 
00630   switch(errcode)
00631   {
00632   case SCSI_ILL_CMD:
00633     state.scsi.sense.data[2] = 0x05;    // illegal request
00634     state.scsi.sense.data[12] = 0x20;   // invalid command
00635     state.scsi.sense.data[13] = 0x00;
00636 #if defined(DEBUG_SCSI)
00637     printf("%s: Command returns check sense status (sense: ILLEGAL COMMAND).\n",
00638            devid_string);
00639 #endif
00640     break;
00641 
00642   case SCSI_LBA_RANGE:
00643     state.scsi.sense.data[2] = 0x05;    // illegal request
00644     state.scsi.sense.data[12] = 0x21;   // LBA out of range
00645     state.scsi.sense.data[13] = 0x00;
00646 #if defined(DEBUG_SCSI)
00647     printf("%s: Command returns check sense status (sense: LBA OUT OF RANGE).\n",
00648            devid_string);
00649 #endif
00650     break;
00651 
00652   case SCSI_TOO_BIG:
00653     state.scsi.sense.data[2] = 0x05;    // illegal request
00654     state.scsi.sense.data[12] = 0x55;   // system resource failure
00655     state.scsi.sense.data[13] = 0x00;
00656 #if defined(DEBUG_SCSI)
00657     printf("%s: Command returns check sense status (sense: SYSTEM RESOURCE FAILURE).\n",
00658          devid_string);
00659 #endif
00660   }
00661 }
00662 
00666 static u32 lba2msf(off_t_large lba)
00667 {
00668 #define PREGAP_SECTORS    150
00669 #define CD_FRAMES_PER_SEC 75
00670 #define CD_MAX_LSN        450150
00671 
00672 #define bin2bcd(x)        ((x / 10) << 4) | (x % 10)
00673   int m;
00674 
00675   int s;
00676 
00677   int f;
00678   lba -= PREGAP_SECTORS;
00679   if(lba >= -PREGAP_SECTORS)
00680   {
00681     m = (lba + PREGAP_SECTORS) / (CD_FRAMES_PER_SEC * 60);
00682     lba -= m * (CD_FRAMES_PER_SEC * 60);
00683     s = (lba + PREGAP_SECTORS) / CD_FRAMES_PER_SEC;
00684     lba -= s * CD_FRAMES_PER_SEC;
00685     f = lba + PREGAP_SECTORS;
00686   }
00687   else
00688   {
00689     m = (lba + CD_MAX_LSN) / (CD_FRAMES_PER_SEC * 60);
00690     lba -= m * (CD_FRAMES_PER_SEC * 60);
00691     s = (lba + CD_MAX_LSN) / CD_FRAMES_PER_SEC;
00692     lba -= s * CD_FRAMES_PER_SEC;
00693     f = lba + CD_MAX_LSN;
00694   }
00695 
00696   if(m > 99)
00697     m = 99;
00698 
00699   //printf("m=%d, s=%d, f=%d == m=%x, s=%x, f=%x\n", m,s,f,bin2bcd(m),bin2bcd(s),bin2bcd(f));
00700   return bin2bcd(m) << 16 | bin2bcd(s) << 8 | bin2bcd(f);
00701 }
00702 
00715 int CDisk::do_scsi_command()
00716 {
00717   unsigned int  retlen = 0;
00718   int           q;
00719   int           pagecode;
00720   u32           ofs = 0;
00721 
00722 #if defined(DEBUG_SCSI)
00723   printf("%s: %d-byte command ", devid_string, state.scsi.cmd.written);
00724   for(unsigned int x = 0; x < state.scsi.cmd.written; x++)
00725     printf("%02x ", state.scsi.cmd.data[x]);
00726   printf("\n");
00727 #endif
00728   if(state.scsi.cmd.written < 1)
00729     return 0;
00730 
00731   if(state.scsi.cmd.data[1] & 0xe0)
00732   {
00733 #if defined(DEBUG_SCSI)
00734     printf("%s: LUN selected...\n", devid_string);
00735 #endif
00736     state.scsi.lun_selected = true;
00737   }
00738 
00739   if(state.scsi.lun_selected && state.scsi.cmd.data[0] != SCSICMD_INQUIRY
00740    && state.scsi.cmd.data[0] != SCSICMD_REQUEST_SENSE)
00741   {
00742     FAILURE_1(NotImplemented, "%s: LUN not supported!\n", devid_string);
00743   }
00744 
00745   switch(state.scsi.cmd.data[0])
00746   {
00747   case SCSICMD_TEST_UNIT_READY:
00748 #if defined(DEBUG_SCSI)
00749     printf("%s: TEST UNIT READY.\n", devid_string);
00750 #endif
00751 
00752     // unit is always ready...
00753     do_scsi_error(SCSI_OK);
00754     break;
00755 
00756   case SCSICMD_REQUEST_SENSE:
00757 #if defined(DEBUG_SCSI)
00758     printf("%s: REQUEST SENSE.\n", devid_string);
00759 #endif
00760     retlen = state.scsi.cmd.data[4];
00761 
00762     //    FAILURE("Sense requested");
00763     if(!state.scsi.sense.available)
00764     {
00765 #if defined(DEBUG_SCSI)
00766       printf("%s: NO SENSE.\n", devid_string);
00767 #endif
00768       state.scsi.sense.data[0] = 0xf0;    // error code
00769       state.scsi.sense.data[1] = 0x00;    // segment number
00770       state.scsi.sense.data[2] = 0x00;    // sense key: no sense
00771       state.scsi.sense.data[3] = 0x00;    // info
00772       state.scsi.sense.data[4] = 0x00;
00773       state.scsi.sense.data[5] = 0x00;
00774       state.scsi.sense.data[6] = 0x00;
00775       state.scsi.sense.data[7] = 10;      // additional sense length
00776       state.scsi.sense.data[8] = 0x00;    // command specific
00777       state.scsi.sense.data[9] = 0x00;
00778       state.scsi.sense.data[10] = 0x00;
00779       state.scsi.sense.data[11] = 0x00;
00780       state.scsi.sense.data[12] = 0x00;   // additional sense code: no additional sense
00781       state.scsi.sense.data[13] = 0x00;   // additional qualifier
00782       state.scsi.sense.data[14] = 0x00;   // FRU code
00783       state.scsi.sense.data[15] = 0x00;   // sense key specific
00784       state.scsi.sense.data[16] = 0x00;
00785       state.scsi.sense.data[17] = 0x00;
00786       state.scsi.sense.available = 18;
00787     }
00788 
00789 #if defined(DEBUG_SCSI)
00790     printf("%s: Returning data: ", devid_string);
00791     for(unsigned int x1 = 0; x1 < state.scsi.sense.available; x1++)
00792       printf("%02x ", state.scsi.sense.data[x1]);
00793     printf("\n");
00794 #endif
00795     state.scsi.dati.read = 0;
00796     state.scsi.dati.available = retlen;
00797     memcpy(state.scsi.dati.data, state.scsi.sense.data,
00798            state.scsi.sense.available);
00799     for(unsigned int x2 = state.scsi.sense.available; x2 < retlen; x2++)
00800       state.scsi.dati.data[x2] = 0;
00801 
00802     do_scsi_error(SCSI_OK);
00803     break;
00804 
00805   case SCSICMD_INQUIRY:
00806     {
00807 #if defined(DEBUG_SCSI)
00808       printf("%s: INQUIRY.\n", devid_string);
00809 #endif
00810       if((state.scsi.cmd.data[1] & 0x1e) != 0x00)
00811       {
00812         FAILURE_2(NotImplemented,
00813                   "%s: Don't know how to handle INQUIRY with cmd[1]=0x%02x.\n",
00814                   devid_string, state.scsi.cmd.data[1]);
00815         break;
00816       }
00817 
00818       u8  qual_dev = state.scsi.lun_selected ? 0x7F : (cdrom() ? 0x05 : 0x00);
00819 
00820       retlen = state.scsi.cmd.data[4];
00821       state.scsi.dati.data[0] = qual_dev; // device type
00822       if(state.scsi.cmd.data[1] & 0x01)
00823       {
00824 
00825         // Vital Product Data
00826         switch(state.scsi.cmd.data[2])
00827         {
00828         case 0x00:
00829 
00830           // Page 0 is basically a list of page codes supported, so if
00831           // any others are added, make sure to insert them in the proper
00832           // place and increase the page length.
00833           state.scsi.dati.data[1] = 0x00; // page code 0
00834           state.scsi.dati.data[2] = 0x00; // reserved
00835           state.scsi.dati.data[3] = 0x02; // page length
00836           state.scsi.dati.data[4] = 0x00; // page 0 is supported.
00837           state.scsi.dati.data[5] = 0x80; // page 0x80 is supported.
00838           break;
00839 
00840         case 0x80:
00841           char serial_number[20];
00842           sprintf(serial_number, "SRL%04x", scsi_initiator_id[0] * 0x0101);
00843 
00844           // unit serial number page
00845           state.scsi.dati.data[1] = 0x80; // page code: 0x80
00846           state.scsi.dati.data[2] = 0x00; // reserved
00847           state.scsi.dati.data[3] = (u8) strlen(serial_number);
00848           memcpy(&state.scsi.dati.data[4], serial_number, strlen(serial_number));
00849           break;
00850 
00851         default:
00852 #if 1
00853           FAILURE_1(NotImplemented,
00854                     "Don't know format for vital product data page %02x!!\n", state.scsi.cmd.data[2]);
00855 #else
00856           state.scsi.dati.data[1] = state.scsi.cmd.data[2]; // page code
00857           state.scsi.dati.data[2] = 0x00; // reserved
00858 #endif
00859         }
00860       }
00861       else
00862       {
00863 
00864         //  Return values:
00865         if(retlen < 36)
00866         {
00867           printf("%s: SCSI inquiry len=%i, <36!\n", devid_string, retlen);
00868           retlen = 36;
00869         }
00870 
00871         state.scsi.dati.data[1] = 0;      // not removable;
00872         state.scsi.dati.data[2] = 0x02;   // ANSI scsi 2
00873         state.scsi.dati.data[3] = 0x02;   // response format
00874         state.scsi.dati.data[4] = 32;     // additional length
00875         state.scsi.dati.data[5] = 0;      // reserved
00876         state.scsi.dati.data[6] = 0x04;   // reserved
00877         state.scsi.dati.data[7] = 0x60;   // capabilities
00878 
00879         //                        vendor  model           rev.
00880         memcpy(&(state.scsi.dati.data[8]), "DEC     RZ58     (C) DEC2000", 28);
00881 
00882         //  Some data is different for CD-ROM drives:
00883         if(cdrom())
00884         {
00885           state.scsi.dati.data[1] = 0x80; //  0x80 = removable
00886 
00887           //                           vendor  model           rev.
00888           memcpy(&(state.scsi.dati.data[8]), "DEC     RRD42   (C) DEC 4.5d", 28);
00889         }
00890       }
00891 
00892       state.scsi.dati.read = 0;
00893       state.scsi.dati.available = retlen;
00894 
00895 #if defined(DEBUG_SCSI)
00896       printf("%s: Returning data: ", devid_string);
00897       for(unsigned int x1 = 0; x1 < 36; x1++)
00898         printf("%02x ", state.scsi.dati.data[x1]);
00899       printf("\n");
00900 #endif
00901       do_scsi_error(SCSI_OK);
00902     }
00903     break;
00904 
00905   case SCSICMD_MODE_SENSE:
00906   case SCSICMD_MODE_SENSE_10:
00907 #if defined(DEBUG_SCSI)
00908     printf("%s: MODE SENSE.\n", devid_string);
00909 #endif
00910     {
00911       int num_blk_desc = 1;
00912 
00913       if(state.scsi.cmd.data[0] == SCSICMD_MODE_SENSE)
00914       {
00915         q = 4;
00916         retlen = state.scsi.cmd.data[4];
00917         state.scsi.dati.data[0] = retlen; // mode data length
00918         state.scsi.dati.data[1] = cdrom() ? 0x01 : 0x00;  // medium type (120 mm data for CD-ROM)
00919         state.scsi.dati.data[2] = 0x00; // device specific parameter
00920         state.scsi.dati.data[3] = 8 * num_blk_desc;       // block descriptor length: 1 page (?)
00921       }
00922       else
00923       {
00924         q = 8;
00925         retlen = state.scsi.cmd.data[7] * 256 + state.scsi.cmd.data[8];
00926         state.scsi.dati.data[0] = (u8) (retlen >> 8);     // mode data length
00927         state.scsi.dati.data[1] = (u8) retlen;
00928         state.scsi.dati.data[2] = cdrom() ? 0x01 : 0x00;  // medium type (120 mm data for CD-ROM)
00929         state.scsi.dati.data[3] = 0x00; // device specific parameter
00930         state.scsi.dati.data[4] = 0x00; // reserved
00931         state.scsi.dati.data[5] = 0x00; // reserved
00932         state.scsi.dati.data[6] = (u8) ((8 * num_blk_desc) >> 8); //  block descriptor length: 1 page (?)
00933         state.scsi.dati.data[7] = (u8) (8 * num_blk_desc);
00934       }
00935 
00936       if((state.scsi.cmd.data[2] & 0xc0) > 0x40)
00937       {
00938         FAILURE_2(NotImplemented, "%s: mode sense, cmd[2] = 0x%02x.\n",
00939                   devid_string, state.scsi.cmd.data[2]);
00940       }
00941 
00942       bool  changeable = ((state.scsi.cmd.data[2] & 0xc0) == 0x40);
00943 
00944       //  Return data:
00945       if(retlen > DATI_BUFSZ)
00946       {
00947         printf("%s: read too big (%d)\n", devid_string, retlen);
00948         do_scsi_error(SCSI_TOO_BIG);
00949         break;
00950       }
00951 
00952       state.scsi.dati.read = 0;
00953       state.scsi.dati.available = retlen; //  Restore size.
00954       pagecode = state.scsi.cmd.data[2] & 0x3f;
00955 
00956       //printf("[ MODE SENSE pagecode=%i ]\n", pagecode);
00957       state.scsi.dati.data[q++] = 0x00;   //  density code
00958       state.scsi.dati.data[q++] = 0;      //  nr of blocks, high (0 = all remaining blocks)
00959       state.scsi.dati.data[q++] = 0;      //  nr of blocks, mid
00960       state.scsi.dati.data[q++] = 0;      //  nr of blocks, low
00961       state.scsi.dati.data[q++] = 0x00;   //  reserved
00962       state.scsi.dati.data[q++] = (u8) (get_block_size() >> 16) & 255;
00963       state.scsi.dati.data[q++] = (u8) (get_block_size() >> 8) & 255;
00964       state.scsi.dati.data[q++] = (u8) (get_block_size() >> 0) & 255;
00965 
00966       for(unsigned int x1 = q; x1 < retlen; x1++)
00967         state.scsi.dati.data[x1] = 0;
00968 
00969       do_scsi_error(SCSI_OK);
00970 
00971       //  descriptors, 8 bytes (each)
00972       //  page, n bytes (each)
00973       switch(pagecode)
00974       {
00975       case SCSIMP_VENDOR: // vendor specific
00976         //  TODO: Nothing here?
00977         break;
00978 
00979       case SCSIMP_READ_WRITE_ERRREC:        //  read-write error recovery page
00980         state.scsi.dati.data[q + 0] = pagecode;
00981         state.scsi.dati.data[q + 1] = 10;
00982         break;
00983 
00984       case SCSIMP_FORMAT_PARAMS:            //  format device page
00985         state.scsi.dati.data[q + 0] = pagecode;
00986         state.scsi.dati.data[q + 1] = 22;
00987         if(!changeable)
00988         {
00989 
00990           //  10,11 = sectors per track
00991           state.scsi.dati.data[q + 10] = 0;
00992           state.scsi.dati.data[q + 11] = (u8) get_sectors();
00993 
00994           //  12,13 = physical sector size
00995           state.scsi.dati.data[q + 12] = (u8) (get_block_size() >> 8) & 255;
00996           state.scsi.dati.data[q + 13] = (u8) (get_block_size() >> 0) & 255;
00997         }
00998         break;
00999 
01000       case SCSIMP_RIGID_GEOMETRY:           //  rigid disk geometry page
01001         state.scsi.dati.data[q + 0] = pagecode;
01002         state.scsi.dati.data[q + 1] = 22;
01003         if(!changeable)
01004         {
01005           state.scsi.dati.data[q + 2] = (u8) (get_cylinders() >> 16) & 255;
01006           state.scsi.dati.data[q + 3] = (u8) (get_cylinders() >> 8) & 255;
01007           state.scsi.dati.data[q + 4] = (u8) get_cylinders() & 255;
01008           state.scsi.dati.data[q + 5] = (u8) get_heads();
01009 
01010           //rpms
01011           state.scsi.dati.data[q + 20] = (7200 >> 8) & 255;
01012           state.scsi.dati.data[q + 21] = 7200 & 255;
01013         }
01014         break;
01015 
01016       case SCSIMP_FLEX_PARAMS:              //  flexible disk page
01017         if(cdrom())
01018         {
01019           FAILURE_1(NotImplemented,
01020                     "%s: CD-ROM write parameter page not implemented.\n", devid_string);
01021         }
01022 
01023         state.scsi.dati.data[q + 0] = pagecode;
01024         state.scsi.dati.data[q + 1] = 0x1e; // length
01025         if(!changeable)
01026         {
01027 
01028           //  2,3 = transfer rate
01029           state.scsi.dati.data[q + 2] = ((5000) >> 8) & 255;
01030           state.scsi.dati.data[q + 3] = (5000) & 255;
01031 
01032           state.scsi.dati.data[q + 4] = (u8) get_heads();
01033           state.scsi.dati.data[q + 5] = (u8) get_sectors();
01034 
01035           //  6,7 = data bytes per sector
01036           state.scsi.dati.data[q + 6] = (u8) (get_block_size() >> 8) & 255;
01037           state.scsi.dati.data[q + 7] = (u8) (get_block_size() >> 0) & 255;
01038 
01039           state.scsi.dati.data[q + 8] = (u8) (get_cylinders() >> 8) & 255;
01040           state.scsi.dati.data[q + 9] = (u8) get_cylinders() & 255;
01041 
01042           //rpms
01043           state.scsi.dati.data[q + 28] = (7200 >> 8) & 255;
01044           state.scsi.dati.data[q + 29] = 7200 & 255;
01045         }
01046         break;
01047 
01048       case SCSIMP_CACHING:  // Caching page
01049         state.scsi.dati.data[q + 0] = pagecode; // page code
01050         state.scsi.dati.data[q + 1] = 0x12;     // page length
01051         if(!changeable)
01052         {
01053 
01054           // 2 = IC,ABPF,CAP,DISC,SIZE,WCE,MF,RCD
01055           //     |  |    |   |    |    |   |  +- read cache disable (0=no)
01056           //     |  |    |   |    |    |   +---- multiplication factor (0=block)
01057           //     |  |    |   |    |    +-------- write cache enable (0=no cache)
01058           //     |  |    |   |    +------------- use cache segment size (0=no)
01059           //     |  |    |   +------------------ prefetch across cyls (1=yes)
01060           //     |  |    +---------------------- cache analysis (0=drive)
01061           //     |  +--------------------------- abort prefetch (1=abrt on cmd)
01062           //     +------------------------------ initiator control (0=drive)
01063           state.scsi.dati.data[q + 2] = 0x0a;
01064 
01065           state.scsi.dati.data[q + 3] = 0;      // read/write cache retention
01066           state.scsi.dati.data[q + 4] = 0x00;   // disable prefetch
01067           state.scsi.dati.data[q + 5] = 0x00;   // for req's greater than this
01068           state.scsi.dati.data[q + 6] = 0;      // minimum prefetch
01069           state.scsi.dati.data[q + 7] = 0;
01070 
01071           state.scsi.dati.data[q + 8] = 0;      // maximum prefetch
01072           state.scsi.dati.data[q + 9] = 0;
01073 
01074           state.scsi.dati.data[q + 10] = 0;     // maximum prefetch ceiling
01075           state.scsi.dati.data[q + 11] = 0;
01076 
01077           state.scsi.dati.data[q + 12] = 0;
01078           state.scsi.dati.data[q + 13] = 0;     // # cache segments
01079           state.scsi.dati.data[q + 14] = 0;     // cache segement size
01080           state.scsi.dati.data[q + 15] = 0;
01081 
01082           state.scsi.dati.data[q + 16] = 0;     // reserved
01083           state.scsi.dati.data[q + 17] = 0;     // non-cache segement size
01084           state.scsi.dati.data[q + 18] = 0;
01085           state.scsi.dati.data[q + 19] = 0;
01086         }
01087         break;
01088 
01089       case SCSIMP_CDROM_CAP:  // CD-ROM capabilities
01090         state.scsi.dati.data[q + 0] = pagecode;
01091         state.scsi.dati.data[q + 1] = 0x14;   // length
01092         if(!changeable)
01093         {
01094           state.scsi.dati.data[q + 2] = 0x03; // read CD-R/CD-RW
01095           state.scsi.dati.data[q + 3] = 0x00; // no write
01096           state.scsi.dati.data[q + 4] = 0x00; // dvd/audio capabilities
01097           state.scsi.dati.data[q + 5] = 0x00; // cd-da capabilities
01098           state.scsi.dati.data[q + 6] = state.scsi.locked ? 0x23 : 0x21;  // tray-loader
01099           state.scsi.dati.data[q + 7] = 0x00;
01100           state.scsi.dati.data[q + 8] = (u8) (2800 >> 8);   // max read speed in kBps (2.8Mbps = 16x)
01101           state.scsi.dati.data[q + 9] = (u8) (2800 >> 0);
01102           state.scsi.dati.data[q + 10] = (u8) (0 >> 8);     // number of volume levels
01103           state.scsi.dati.data[q + 11] = (u8) (0 >> 0);
01104           state.scsi.dati.data[q + 12] = (u8) (64 >> 8);    // buffer size in KBytes
01105           state.scsi.dati.data[q + 13] = (u8) (64 >> 0);
01106           state.scsi.dati.data[q + 14] = (u8) (2800 >> 8);  // current read speed
01107           state.scsi.dati.data[q + 15] = (u8) (2800 >> 0);
01108           state.scsi.dati.data[q + 16] = 0; // reserved
01109           state.scsi.dati.data[q + 17] = 0; // digital output format
01110           state.scsi.dati.data[q + 18] = (u8) (0 >> 8); // max write speed
01111           state.scsi.dati.data[q + 19] = (u8) (0 >> 0);
01112           state.scsi.dati.data[q + 20] = (u8) (0 >> 8); // current write speed
01113           state.scsi.dati.data[q + 21] = (u8) (0 >> 0);
01114         }
01115         break;
01116 
01117       default:
01118         FAILURE_2(NotImplemented,
01119                   "%s: MODE_SENSE for page %i is not yet implemented!\n", devid_string,
01120                   pagecode);
01121       }
01122 
01123 #if defined(DEBUG_SCSI)
01124       printf("%s: Returning data: ", devid_string);
01125       for(unsigned int x1 = 0; x1 < q + 30; x1++)
01126         printf("%02x ", state.scsi.dati.data[x1]);
01127       printf("\n");
01128 #endif
01129     }
01130     break;
01131 
01132   case SCSICMD_PREVENT_ALLOW_REMOVE:
01133     if(state.scsi.cmd.data[4] & 1)
01134     {
01135       state.scsi.locked = true;
01136 #if defined(DEBUG_SCSI)
01137       printf("%s: PREVENT MEDIA REMOVAL.\n", devid_string);
01138 #endif
01139     }
01140     else
01141     {
01142       state.scsi.locked = false;
01143 #if defined(DEBUG_SCSI)
01144       printf("%s: ALLOW MEDIA REMOVAL.\n", devid_string);
01145 #endif
01146     }
01147 
01148     do_scsi_error(SCSI_OK);
01149     break;
01150 
01151   case SCSICMD_MODE_SELECT:
01152 
01153     // get data out first...
01154     state.scsi.dato.expected = 12;
01155     if(state.scsi.dato.written < state.scsi.dato.expected)
01156       return 2;
01157 
01158 #if defined(DEBUG_SCSI)
01159     printf("%s: MODE SELECT.\n", devid_string);
01160     printf("Data: ");
01161     for(unsigned int x = 0; x < state.scsi.dato.written; x++)
01162       printf("%02x ", state.scsi.dato.data[x]);
01163     printf("\n");
01164 #endif
01165     if(state.scsi.cmd.written == 6 && state.scsi.dato.written == 12
01166      && state.scsi.dato.data[0] == 0x00         // data length
01167        //&& state.scsi.dato.data[1] == 0x05 // medium type - ignore
01168      && state.scsi.dato.data[2] == 0x00         // dev. specific
01169      && state.scsi.dato.data[3] == 0x08         // block descriptor length
01170      && state.scsi.dato.data[4] == 0x00         // density code
01171      && state.scsi.dato.data[5] == 0x00         // all blocks
01172      && state.scsi.dato.data[6] == 0x00         // all blocks
01173      && state.scsi.dato.data[7] == 0x00         // all blocks
01174      && state.scsi.dato.data[8] == 0x00)        // reserved
01175     {
01176       set_block_size((state.scsi.dato.data[9] << 16) |
01177                      (state.scsi.dato.data[10] << 8) | state.scsi.dato.data[11]);
01178 #if defined(DEBUG_SCSI)
01179       printf("%s: Block size set to %d.\n", devid_string, get_block_size());
01180 #endif
01181     }
01182     else
01183     {
01184       unsigned int  x;
01185       printf("%s: MODE SELECT ignored.\nCommand: ", devid_string);
01186       for(x = 0; x < state.scsi.cmd.written; x++)
01187         printf("%02x ", state.scsi.cmd.data[x]);
01188       printf("\nData: ");
01189       for(x = 0; x < state.scsi.dato.written; x++)
01190         printf("%02x ", state.scsi.dato.data[x]);
01191       printf("\nThis might be an attempt to change our blocksize or something like that...\nPlease check the above data, then press enter.\n>");
01192       getchar();
01193     }
01194 
01195     // ignore it...
01196     do_scsi_error(SCSI_OK);
01197     break;
01198 
01199   case SCSIBLOCKCMD_READ_CAPACITY:
01200 #if defined(DEBUG_SCSI)
01201     printf("%s: READ CAPACITY.\n", devid_string);
01202 #endif
01203     if(state.scsi.cmd.data[8] & 1)
01204     {
01205       FAILURE_1(NotImplemented,
01206                 "%s: Don't know how to handle READ CAPACITY with PMI bit set.\n",
01207                 devid_string);
01208       break;
01209     }
01210 
01211     // READ CAPACITY returns the number of the last LBA (n-1);
01212     // not the number of LBA's (n)
01213     state.scsi.dati.data[0] = (u8) ((get_lba_size() - 1) >> 24) & 255;
01214     state.scsi.dati.data[1] = (u8) ((get_lba_size() - 1) >> 16) & 255;
01215     state.scsi.dati.data[2] = (u8) ((get_lba_size() - 1) >> 8) & 255;
01216     state.scsi.dati.data[3] = (u8) ((get_lba_size() - 1) >> 0) & 255;
01217 
01218     state.scsi.dati.data[4] = (u8) (get_block_size() >> 24) & 255;
01219     state.scsi.dati.data[5] = (u8) (get_block_size() >> 16) & 255;
01220     state.scsi.dati.data[6] = (u8) (get_block_size() >> 8) & 255;
01221     state.scsi.dati.data[7] = (u8) (get_block_size() >> 0) & 255;
01222 
01223     state.scsi.dati.read = 0;
01224     state.scsi.dati.available = 8;
01225 
01226 #if defined(DEBUG_SCSI)
01227     printf("%s: Returning data: ", devid_string);
01228     for(unsigned int x1 = 0; x1 < 8; x1++)
01229       printf("%02x ", state.scsi.dati.data[x1]);
01230     printf("\n");
01231 #endif
01232     do_scsi_error(SCSI_OK);
01233     break;
01234 
01235   case SCSICMD_READ:
01236   case SCSICMD_READ_10:
01237   case SCSICMD_READ_12:
01238   case SCSICMD_READ_CD:
01239 #if defined(DEBUG_SCSI)
01240     printf("%s: READ.\n", devid_string);
01241 #endif
01242 
01243     //if (state.scsi.disconnect_priv)
01244     //{
01245     //  //printf("%s: Will disconnect before returning read data.\n", devid_string);
01246     //  state.scsi.will_disconnect = true;
01247     //}
01248     if(state.scsi.cmd.data[0] == SCSICMD_READ)
01249     {
01250 
01251       //  bits 4..0 of cmd[1], and cmd[2] and cmd[3]
01252       //  hold the logical block address.
01253       //
01254       //  cmd[4] holds the number of logical blocks
01255       //  to transfer. (Special case if the value is
01256       //  0, actually means 256.)
01257       ofs = ((state.scsi.cmd.data[1] & 0x1f) << 16) + (state.scsi.cmd.data[2] << 8) + state.scsi.cmd.data[3];
01258       retlen = state.scsi.cmd.data[4];
01259       if(retlen == 0)
01260         retlen = 256;
01261     }
01262     else if(state.scsi.cmd.data[0] == SCSICMD_READ_10)
01263     {
01264 
01265       //  cmd[2..5] hold the logical block address.
01266       //  cmd[7..8] holds the number of logical
01267       ofs = (state.scsi.cmd.data[2] << 24) + (state.scsi.cmd.data[3] << 16) + (state.scsi.cmd.data[4] << 8) + state.scsi.cmd.data[5];
01268       retlen = (state.scsi.cmd.data[7] << 8) + state.scsi.cmd.data[8];
01269     }
01270     else if(state.scsi.cmd.data[0] == SCSICMD_READ_12)
01271     {
01272 
01273       //  cmd[2..5] hold the logical block address.
01274       //  cmd[6..9] holds the number of logical
01275       ofs = (state.scsi.cmd.data[2] << 24) + (state.scsi.cmd.data[3] << 16) + (state.scsi.cmd.data[4] << 8) + state.scsi.cmd.data[5];
01276       retlen = (state.scsi.cmd.data[6] << 24) + (state.scsi.cmd.data[7] << 16) + (state.scsi.cmd.data[8] << 8) + state.scsi.cmd.data[9];
01277     }
01278     else if(state.scsi.cmd.data[0] == SCSICMD_READ_CD)
01279     {
01280       if(state.scsi.cmd.data[9] != 0x10)
01281       {
01282         FAILURE_2(NotImplemented, "%s: READ CD issued with data type %02x.\n",
01283                   devid_string, state.scsi.cmd.data[9]);
01284       }
01285 
01286       //  cmd[2..5] hold the logical block address.
01287       //  cmd[6..8] holds the number of logical blocks to transfer.
01288       ofs = (state.scsi.cmd.data[2] << 24) + (state.scsi.cmd.data[3] << 16) + (state.scsi.cmd.data[4] << 8) + state.scsi.cmd.data[5];
01289       retlen = (state.scsi.cmd.data[6] << 16) +
01290         (state.scsi.cmd.data[7] << 8) +
01291         state.scsi.cmd.data[8];
01292     }
01293 
01294     // Within bounds?
01295     if((ofs + retlen) > get_lba_size())
01296     {
01297       do_scsi_error(SCSI_LBA_RANGE);
01298       break;
01299     }
01300 
01301     // Would exceed buffer?
01302     if(retlen > DATI_BUFSZ)
01303     {
01304       printf("%s: read too big (%d)\n", devid_string, retlen);
01305       do_scsi_error(SCSI_TOO_BIG);
01306       break;
01307     }
01308 
01309     //  Return data:
01310     seek_block(ofs);
01311     read_blocks(state.scsi.dati.data, retlen);
01312     state.scsi.dati.read = 0;
01313     state.scsi.dati.available = retlen * get_block_size();
01314 
01315 #if defined(DEBUG_SCSI)
01316     printf("%s: READ  ofs=%d size=%d\n", devid_string, ofs, retlen);
01317 #endif
01318     do_scsi_error(SCSI_OK);
01319     break;
01320 
01321   case SCSICMD_READ_LONG:
01322 #if defined(DEBUG_SCSI)
01323     printf("%s: READ_LONG.\n", devid_string);
01324 #endif
01325 
01326     // The read long command is used to read one block of disk data, including
01327     // ECC data. OpenVMS uses read long / write long to do host-based shadowing.
01328     // During driver initialization, OpenVMS will check each disk to see if it
01329     // supports host-based shadowing, by trying to find the right size for read
01330     // long commands. The emulated scsi disk sets the size for read long / write
01331     // long commands to 514 bytes (the first value OpenVMS tries).
01332     //  cmd[2..5] hold the logical block address.
01333     //  cmd[7..8] holds the number of bytes to transfer
01334     ofs = (state.scsi.cmd.data[2] << 24) + (state.scsi.cmd.data[3] << 16) + (state.scsi.cmd.data[4] << 8) + state.scsi.cmd.data[5];
01335     retlen = (state.scsi.cmd.data[7] << 8) + state.scsi.cmd.data[8];
01336 
01337     state.scsi.stat.available = 1;
01338     state.scsi.stat.data[0] = 0;
01339     state.scsi.stat.read = 0;
01340     state.scsi.msgi.available = 1;
01341     state.scsi.msgi.data[0] = 0;
01342     state.scsi.msgi.read = 0;
01343 
01344     // If the requested size is not 514 bytes, don't accept it.
01345     if(retlen != 514)
01346     {
01347       do_scsi_error(SCSI_ILL_CMD);
01348       break;
01349     }
01350 
01351     // Within bounds?
01352     if((ofs + 1) > get_lba_size())
01353     {
01354       do_scsi_error(SCSI_LBA_RANGE);
01355       break;
01356     }
01357 
01358     // Would exceed buffer?
01359     if(retlen > DATI_BUFSZ)
01360     {
01361       printf("%s: read too big (%d)\n", devid_string, retlen);
01362       do_scsi_error(SCSI_TOO_BIG);
01363       break;
01364     }
01365 
01366     //  Return data:
01367     seek_block(ofs);
01368     read_blocks(state.scsi.dati.data, 1);
01369     for(unsigned int x1 = get_block_size(); x1 < retlen; x1++)
01370       state.scsi.dati.data[x1] = 0;             // set ECC bytes to 0.
01371     state.scsi.dati.read = 0;
01372     state.scsi.dati.available = retlen;
01373     do_scsi_error(SCSI_OK);
01374     break;
01375 
01376   case SCSICMD_WRITE:
01377   case SCSICMD_WRITE_10:
01378 #if defined(DEBUG_SCSI)
01379     printf("%s: WRITE.\n", devid_string);
01380 #endif
01381     if(state.scsi.cmd.data[0] == SCSICMD_WRITE)
01382     {
01383 
01384       //  bits 4..0 of cmd[1], and cmd[2] and cmd[3]
01385       //  hold the logical block address.
01386       //
01387       //  cmd[4] holds the number of logical blocks
01388       //  to transfer. (Special case if the value is
01389       //  0, actually means 256.)
01390       ofs = ((state.scsi.cmd.data[1] & 0x1f) << 16) + (state.scsi.cmd.data[2] << 8) + state.scsi.cmd.data[3];
01391       retlen = state.scsi.cmd.data[4];
01392       if(retlen == 0)
01393         retlen = 256;
01394     }
01395     else
01396     {
01397 
01398       //  cmd[2..5] hold the logical block address.
01399       //  cmd[7..8] holds the number of logical blocks
01400       //  to transfer.
01401       ofs = (state.scsi.cmd.data[2] << 24) + (state.scsi.cmd.data[3] << 16) + (state.scsi.cmd.data[4] << 8) + state.scsi.cmd.data[5];
01402       retlen = (state.scsi.cmd.data[7] << 8) + state.scsi.cmd.data[8];
01403     }
01404 
01405     // Within bounds?
01406     if(((ofs + retlen)) > get_lba_size())
01407     {
01408       do_scsi_error(SCSI_LBA_RANGE);
01409       break;
01410     }
01411 
01412     // Would exceed buffer?
01413     if(retlen * get_block_size() > DATO_BUFSZ)
01414     {
01415       printf("%s: write too big (%d)\n", devid_string,
01416              (int) (retlen * get_block_size()));
01417       do_scsi_error(SCSI_TOO_BIG);
01418       break;
01419     }
01420 
01421     state.scsi.dato.expected = retlen * get_block_size();
01422 
01423     if(state.scsi.dato.written < state.scsi.dato.expected)
01424       return 2;
01425 
01426     //  Write data
01427     seek_block(ofs);
01428     write_blocks(state.scsi.dato.data, retlen);
01429 
01430 #if defined(DEBUG_SCSI)
01431     printf("%s: WRITE  ofs=%d size=%d\n", devid_string, ofs, retlen);
01432 #endif
01433     do_scsi_error(SCSI_OK);
01434     break;
01435 
01436   case SCSICMD_SYNCHRONIZE_CACHE:
01437 #if defined(DEBUG_SCSI)
01438     printf("%s: SYNCHRONIZE CACHE.\n", devid_string);
01439 #endif
01440     do_scsi_error(SCSI_OK);
01441     break;
01442 
01443   case SCSICDROM_READ_TOC:
01444     {
01445 #if defined(DEBUG_SCSI)
01446       printf("%s: CDROM READ TOC.\n", devid_string);
01447 #endif
01448       if(state.scsi.cmd.data[2] & 0x0f)
01449       {
01450         FAILURE_2(NotImplemented,
01451                   "%s: I don't understand READ TOC/PMA/ATIP with format %01x.\n",
01452                   devid_string, state.scsi.cmd.data[2] & 0x0f);
01453       }
01454 
01455       if(state.scsi.cmd.data[6] > 1 && state.scsi.cmd.data[6] != 0xAA)
01456       {
01457         FAILURE_2(InvalidArgument, "%s: I don't know CD-ROM track 0x%02x.\n",
01458                   devid_string, state.scsi.cmd.data[6]);
01459       }
01460 
01461       retlen = state.scsi.cmd.data[7] * 256 + state.scsi.cmd.data[8];
01462 
01463       state.scsi.dati.available = retlen;
01464       state.scsi.dati.read = 0;
01465 
01466       int q = 2;
01467 
01468       /*Here's an actual response from a single-track pressed CD to the 
01469             command  0x43, 00, 00, 00, 00, 00, 00, 00, 0x0c, 0x40, 00, 00
01470 
01471             0000 00 0a 01 01 00 14 01 00 00 00 00 00 00 00 00 00 ................
01472             0010 00 43 d6 02 00 81 ff ff 19 00 00 00 00 00 00 00 .C..............
01473             0020 01 00 00 00 00 00 00 00 01 00 00 00 01 00 01 00 ................
01474             0030 00 00 00 00 00 10 00 00 00 10 00 00 01 00 00 00 ................
01475       */
01476       state.scsi.dati.data[q++] = 1;            // first track
01477       state.scsi.dati.data[q++] = 1;            // last track
01478       if(state.scsi.cmd.data[6] <= 1)
01479       {
01480         state.scsi.dati.data[q++] = 0;          // reserved
01481         state.scsi.dati.data[q++] = 0x14;       // adr/control (Q-channel: current position, data track, no copy)
01482         state.scsi.dati.data[q++] = 1;          // track number
01483         state.scsi.dati.data[q++] = 0;          // reserved
01484         if(state.scsi.cmd.data[1] & 0x02)
01485         {
01486           u32 x = lba2msf(0);
01487           state.scsi.dati.data[q++] = 0;
01488           state.scsi.dati.data[q++] = (x & 0xff0000) >> 16;
01489           state.scsi.dati.data[q++] = (x & 0xff00) >> 8;
01490           state.scsi.dati.data[q++] = x & 0xff;
01491         }
01492         else
01493         {
01494           state.scsi.dati.data[q++] = 0 >> 24;  //lba
01495           state.scsi.dati.data[q++] = 0 >> 16;
01496           state.scsi.dati.data[q++] = 0 >> 8;
01497           state.scsi.dati.data[q++] = 0;
01498         }
01499       }
01500 
01501       state.scsi.dati.data[q++] = 0;            // reserved
01502       state.scsi.dati.data[q++] = 0x16;         // adr/control (Q-channel: current position, data track, copy)
01503       state.scsi.dati.data[q++] = 0xAA;         // track number
01504       state.scsi.dati.data[q++] = 0;            // reserved
01505       if(state.scsi.cmd.data[1] & 0x02)
01506       {
01507         u32 x = lba2msf(get_lba_size());
01508         state.scsi.dati.data[q++] = 0;
01509         state.scsi.dati.data[q++] = (x & 0xff0000) >> 16;
01510         state.scsi.dati.data[q++] = (x & 0xff00) >> 8;
01511         state.scsi.dati.data[q++] = x & 0xff;
01512       }
01513       else
01514       {
01515         state.scsi.dati.data[q++] = (u8) (get_lba_size() >> 24);  //lba
01516         state.scsi.dati.data[q++] = (u8) (get_lba_size() >> 16);
01517         state.scsi.dati.data[q++] = (u8) (get_lba_size() >> 8);
01518         state.scsi.dati.data[q++] = (u8) get_lba_size();
01519       }
01520 
01521       state.scsi.dati.data[0] = (u8) (q >> 8);
01522       state.scsi.dati.data[1] = (u8) q;
01523 
01524 #if defined(DEBUG_SCSI)
01525       printf("%s: Returning data: ", devid_string);
01526       for(unsigned int x1 = 0; x1 < q; x1++)
01527         printf("%02x ", state.scsi.dati.data[x1]);
01528       printf("\n");
01529 #endif
01530       do_scsi_error(SCSI_OK);
01531     }
01532     break;
01533 
01534   case SCSICDRRW_FORMAT:
01535   case SCSICDRRW_READ_DISC_INFO:
01536   case SCSICDRRW_READ_TRACK_INFO:
01537   case SCSICDRRW_RESERVE_TRACK:
01538   case SCSICDRRW_SEND_OPC_INFO:
01539   case SCSICDRRW_REPAIR_TRACK:
01540   case SCSICDRRW_READ_MASTER_CUE:
01541   case SCSICDRRW_CLOSE_TRACK:
01542   case SCSICDRRW_READ_BUFFER_CAP:
01543   case SCSICDRRW_SEND_CUE_SHEET:
01544   case SCSICDRRW_BLANK:
01545 
01546     // These are CD-R/RW specific commands; we pretend to be a simple
01547     // CD-ROM player, so no support for these commands.
01548 #if defined(DEBUG_SCSI)
01549     printf("%s: CD-R/RW specific.\n", devid_string);
01550 #endif
01551     do_scsi_error(SCSI_ILL_CMD);
01552     break;
01553 
01554   default:
01555     FAILURE_2(NotImplemented, "%s: Unknown SCSI command 0x%02x.\n",
01556               devid_string, state.scsi.cmd.data[0]);
01557   }
01558 
01559   return 0;
01560 }
01561 
01569 int CDisk::do_scsi_message()
01570 {
01571   unsigned int  msg;
01572   unsigned int  msglen;
01573 
01574   msg = 0;
01575   while(msg < state.scsi.msgo.written)
01576   {
01577     if(state.scsi.msgo.data[msg] & 0x80)
01578     {
01579 
01580       // identify
01581 #if defined(DEBUG_SCSI)
01582       printf("%s: MSG: identify", devid_string);
01583 #endif
01584       if(state.scsi.msgo.data[msg] & 0x40)
01585       {
01586 #if defined(DEBUG_SCSI)
01587         printf(" w/disconnect priv");
01588 #endif
01589 
01590         //        state.scsi.disconnect_priv = true;
01591       }
01592 
01593       if(state.scsi.msgo.data[msg] & 0x07)
01594       {
01595 
01596         // LUN...
01597 #if defined(DEBUG_SCSI)
01598         printf(" for lun %d%", state.scsi.msgo.data[msg] & 0x07);
01599 #endif
01600         state.scsi.lun_selected = true;
01601       }
01602 
01603 #if defined(DEBUG_SCSI)
01604       printf("\n");
01605 #endif
01606       msg++;
01607     }
01608     else
01609     {
01610       switch(state.scsi.msgo.data[msg])
01611       {
01612       case 0x01:
01613 #if defined(DEBUG_SCSI)
01614         printf("%s: MSG: extended: ", devid_string);
01615 #endif
01616         msglen = state.scsi.msgo.data[msg + 1];
01617         msg += 2;
01618         switch(state.scsi.msgo.data[msg])
01619         {
01620         case 0x01:
01621           {
01622 #if defined(DEBUG_SCSI)
01623             printf("SDTR.\n");
01624 #endif
01625             state.scsi.msgi.available = msglen + 2;
01626             state.scsi.msgi.data[0] = 0x01;
01627             state.scsi.msgi.data[1] = msglen;
01628             for(unsigned int x = 0; x < msglen; x++)
01629               state.scsi.msgi.data[2 + x] = state.scsi.msgo.data[msg + x];
01630           }
01631           break;
01632 
01633         case 0x03:
01634           {
01635 #if defined(DEBUG_SCSI)
01636             printf("WDTR.\n");
01637 #endif
01638             state.scsi.msgi.available = msglen + 2;
01639             state.scsi.msgi.data[0] = 0x01;
01640             state.scsi.msgi.data[1] = msglen;
01641             for(unsigned int x = 0; x < msglen; x++)
01642               state.scsi.msgi.data[2 + x] = state.scsi.msgo.data[msg + x];
01643           }
01644           break;
01645 
01646         default:
01647           FAILURE_2(NotImplemented,
01648                     "%s: MSG: don't understand extended message %02x.\n", devid_string,
01649                     state.scsi.msgo.data[msg]);
01650         }
01651 
01652         msg += msglen;
01653         break;
01654 
01655       default:
01656         FAILURE_2(NotImplemented, "%s: MSG: don't understand message %02x.\n",
01657                   devid_string, state.scsi.msgo.data[msg]);
01658       }
01659     }
01660   }
01661 
01662   // return next phase
01663   if(state.scsi.msgi.available)
01664     return SCSI_PHASE_MSG_IN;
01665   else
01666     return SCSI_PHASE_COMMAND;
01667 }
01668 
01669 static int  primes_54[54] = { 2,  3,    5,   7,  11,  13,  17,  19,  23,  29,
01670   31,  37,  41,  43,  47,  53,  59,  61,  67,  71,
01671   73,  79,  83,  89,  97, 101, 103, 107, 109, 113,
01672   127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
01673   179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
01674   233, 239, 241, 251};
01675 
01676 //  2 3 5 7 11 13
01677 static int  pri16[16][6] = { {4,0,0,0, 0, 0}, //16
01678   {0,1,1,0, 0, 0},  //15
01679   {1,0,0,1, 0, 0},  //14
01680   {0,0,0,0, 0, 1},  //13
01681   {2,1,0,0, 0, 0},  //12
01682   {0,0,0,0, 1, 0},  //11
01683   {1,0,1,0, 0, 0},  //10
01684   {0,2,0,0, 0, 0},  //9
01685   {3,0,0,0, 0, 0},  //8
01686   {0,0,0,1, 0, 0},  //7
01687   {1,1,0,0, 0, 0},  //6
01688   {0,0,1,0, 0, 0},  //5
01689   {2,0,0,0, 0, 0},  //4
01690   {0,1,0,0, 0, 0},  //3
01691   {1,0,0,0, 0, 0},  //2
01692   {0,0,0,0, 0, 0}}; //1
01693 static off_t_large get_primes(off_t_large value, int pri[54])
01694 {
01695   int i;
01696   for(i = 0; i < 54; i++)
01697   {
01698     pri[i] = 0;
01699     while(!(value % primes_54[i]))
01700     {
01701       pri[i]++;
01702       value /= primes_54[i];
01703     }
01704   }
01705 
01706   return value;
01707 }
01708 
01712 #define MAX_HD  16
01713 #define MAX_SEC 50
01714 
01715 void CDisk::determine_layout()
01716 {
01717   int   disk_primes[54];
01718   int   compare_primes[54];
01719 
01720   long  heads_sectors = 0;
01721   long  c_heads = 0;
01722   bool  b;
01723   int   prime;
01724 
01725   get_primes(get_lba_size(), disk_primes);
01726 
01727   for(heads_sectors = MAX_SEC * MAX_HD; heads_sectors > 0; heads_sectors--)
01728   {
01729     if(get_primes(heads_sectors, compare_primes) > 1)
01730       continue;
01731 
01732     for(c_heads = MAX_HD; c_heads > 0; c_heads--)
01733     {
01734       b = true;
01735       for(prime = 0; prime < 6; prime++)
01736       {
01737         if(pri16[16 - c_heads][prime] > compare_primes[prime])
01738         {
01739           b = false;
01740           break;
01741         }
01742       }
01743 
01744       if(b)
01745         break;
01746     }
01747 
01748     if(heads_sectors / c_heads > MAX_SEC)
01749       continue;
01750 
01751     b = true;
01752     for(prime = 0; prime < 54; prime++)
01753     {
01754       if(compare_primes[prime] > disk_primes[prime])
01755       {
01756         b = false;
01757         break;
01758       }
01759     }
01760 
01761     if(b)
01762       break;
01763   }
01764 
01765   heads = c_heads;
01766   sectors = heads_sectors / c_heads;
01767 
01768   //  sectors = 32;
01769   //  heads = 8;
01770   cylinders = get_lba_size() / heads / sectors;
01771 }

SourceForge.net Logo
Project space on SourceForge.net