home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / suntar1.cpt / diskDriver.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-15  |  30.5 KB  |  1,068 lines

  1. /*******************************************************************************\
  2.  
  3. disk driver interface module
  4.  
  5. suntar 1.3, ⌐1991-92 Sauro & Gabriele Speranza
  6.  
  7. This program is public domain, feel free to use it or part of it for anything
  8.  
  9. \*******************************************************************************/
  10.  
  11.  
  12. #include "PB_sync.h"
  13. #include "antiglue.h"
  14.  
  15. #include    <DiskDvr.h>
  16. #include    <DeviceMgr.h>
  17.  
  18. #include "windows.h"
  19. #include "suntar.h"
  20.  
  21. #define dp printf
  22.  
  23. #define SINGLE_SIDED    2
  24. #define TWO_SIDED    3
  25. #define SUPERDRIVE    4
  26.  
  27.  
  28. extern short n_superdrives,last_drive,preferred_drive;
  29. extern short drive_type[max_drive];
  30. extern Boolean disco_espulso;
  31. extern sector_t file_current_s;
  32.  
  33.  
  34. OSErr get_format(DrvSts*,char*);
  35. Boolean is_msdos_disk(int);
  36. void verify_sectors(sector_t,char *,int);
  37.  
  38. enum os_type riconosci_disco_mac(sector_2)
  39. unsigned char sector_2[512];
  40. {
  41. /* sector 2 contains the essential informations about the disk in both MFS and HFS */
  42. enum os_type i;
  43.  
  44. if( *(int*) sector_2== 0xD2D7 )
  45.     i=mac_MFS;
  46. else if( *(int*) sector_2== 0x4244)
  47.     i=mac_HFS;
  48. else
  49.     return unknown_os;
  50.  
  51. if( sector_2[36]<=27 /*lunghezza del nome*/ &&
  52.         *(int*)§or_2[12]>0 /* numero di files nel disco */)
  53.     return i;
  54.  else
  55.      return unknown_os;    /* two possible 16 bit values means 1 probability
  56.                          out of 32768 to recognize as Mac disk a non-Mac one,
  57.                          testing some other fields decreases it... */
  58. }
  59.  
  60.  
  61. static Boolean is_msdos_disk(drive_n)
  62. {
  63. /* ms-dos does not define a field containing some fixed value, but some
  64. fields are much larger than the small numbers they should hold, hence there is much
  65. redundancy, if all those fields have reasonable values, and at least some are not
  66. zero, then it must be an ms-dos disk
  67. Attention ! It uses the value of sectors_on_floppy which must be set to the correct
  68. value for the disk
  69. */
  70.  
  71. struct bootsector {        /* from mtools, msdos.h */
  72. /*0*/    unsigned char jump[3];        /* Jump to boot code */
  73. /*3*/    unsigned char banner[8];    /* OEM name & version */
  74. /*11*/    unsigned char secsiz[2];    /* Bytes per sector hopefully 512 */
  75. /*13*/    unsigned char clsiz;        /* Cluster size in sectors */
  76. /*14*/    unsigned char nrsvsect[2];    /* Number of reserved (boot) sectors */
  77. /*16*/    unsigned char nfat;            /* Number of FAT tables hopefully 2 */
  78. /*17*/    unsigned char dirents[2];    /* Number of directory slots */
  79. /*19*/    unsigned char psect[2];        /* Total sectors on disk */
  80. /*21*/    unsigned char descr;        /* Media descriptor=first byte of FAT */
  81. /*22*/    unsigned char fatlen[2];    /* Sectors in FAT */
  82. /*24*/    unsigned char nsect[2];        /* Sectors/track */
  83. /*26*/    unsigned char nheads[2];    /* Heads */
  84. /*28*/    unsigned char nhs[2];        /* number of hidden sectors */
  85. /*30*/    unsigned char junk[482];    /* who cares? */
  86. };
  87.  
  88.  
  89. unsigned char buffer[512];
  90. int i;
  91. unsigned short n_s;
  92. Boolean maybe_old;
  93. static unsigned char offs[]= {11,12,13,15,16,18,23,25,26,27};
  94. static unsigned char limit[]={0, 2, 4, 0, 2, 2, 0, 0, 2, 0};
  95. static unsigned char min[]=  {0, 2, 0, 0, 1, 0, 0, 0, 1, 0};
  96.  
  97. read_one_sector(0,buffer,drive_n);
  98. if(err_code) return false;
  99.  
  100. maybe_old=false;
  101. for(i=0;i<sizeof(offs);i++)
  102.     if((unsigned char)buffer[offs[i]]>limit[i] ||
  103.        (unsigned char)buffer[offs[i]]<min[i]){
  104.         if(i<7) return false;
  105.         maybe_old=true;    /* those fields don't exist in disks formatted by a very 
  106.                         old version of ms-dos */
  107.         }
  108.  
  109. lowbyte(n_s)= buffer[19];
  110. highbyte(n_s)= buffer[20];
  111.  
  112. if(buffer[24]==0 || n_s != sectors_on_floppy || n_s%buffer[24]!=0 )
  113.     maybe_old=true;
  114.         /* bisogna accettare 9 e 18 ma anche 8 (160K) e 16 (320K) e 15 (1200K) 
  115.         e tanto vale anche un numero di settori qualunque purche' multiplo intero 
  116.         del numero di settori per traccia (a meno che l'hardware possa fornire i 
  117.         "veri" valori per questi parametri)
  118.         -- I can't test the exact value of sectors per track since somebody
  119.         could find a way to connect to the .Sony driver a disk which is not
  120.         720 nor 1440, but 360, 1200 or even the now obsolete 180, 160 and 320K
  121.         formats
  122.         */
  123. if(!maybe_old) return true;
  124. /* pero' in quei casi, la FAT sta comunque nel settore 1 e il primo byte della
  125. FAT (byte 0) vale FE o FC o FD o FF a seconda della densita' (160,180,320,360)
  126. -- in very old DOS some of the test variables were not defined, the remaining
  127. ones are too few to guarantee good probabilities of correctly guessing, but
  128. in those cases the FAT is in sector 1 and the first byte of FAT is
  129. FE or FC or FD or FF according to the density (160,180,320,360)
  130. */
  131. if(buffer[21]>=0xFC /* && buffer[21]<=0xFF */)
  132.     return true;
  133. read_one_sector(1,buffer,drive_n);
  134. if(!err_code && buffer[0]>=0xFC)
  135.     return true;
  136. return false;
  137. }
  138.  
  139. /***********************************************************************/
  140.  
  141.  
  142. static Handle icon_handle;
  143. static Rect iconRect={10,16,42,48};
  144.  
  145.  
  146. pascal Boolean icon_update (DialogPtr,EventRecord *,short *);
  147. static pascal Boolean icon_update (theDialog, theEvent,itemHit)
  148. /* update routine for the disk initialization dialog: we've tried to
  149. copy the standard disk initialization dialog used by DIBadMount
  150. */
  151. DialogPtr theDialog;
  152. EventRecord *theEvent;
  153. short *itemHit;
  154. {
  155. if(theEvent->what==keyDown &&  ((unsigned char) theEvent->message==enter_key || 
  156.    (unsigned char) theEvent->message==CR)){
  157.     Rect frameRect;
  158.     short    kind;
  159.     Handle    h;
  160.     *itemHit=1;
  161.     GetDItem(theDialog,1,&kind,&h,&frameRect);
  162.     SelectButton(h);
  163.     return true;
  164.     }
  165. else if(theEvent->what==updateEvt){
  166.     if((WindowPtr)theEvent->message==theDialog){
  167.         GrafPtr    savePort;
  168.         Rect frameRect;
  169.         short    kind;
  170.         Handle    h;
  171.  
  172.         GetPort( &savePort );    
  173.         SetPort(theDialog);
  174.         PlotIcon(&iconRect,icon_handle);
  175.         GetDItem(theDialog,1,&kind,&h,&frameRect);
  176.         OutlineControl(h);
  177.  
  178.         SetPort(savePort);
  179.         }
  180.     else
  181.         UpdateFilter(theEvent);
  182.     }
  183. else if(theEvent->what==activateEvt)
  184.         UpdateFilter(theEvent);
  185.  
  186. return false;
  187. }
  188.  
  189.  
  190. void disk_format(make_dir)        /* disk initialization routine */
  191. Boolean make_dir;
  192. {
  193. /* see Technical Notes 70 and 272 */
  194.  
  195. extern Point badmount_point;
  196. cntrlParam       ParamBlock;
  197. DialogTHndl    dHandle;
  198. DialogPtr myDialog;
  199. int item,err;
  200.  
  201.  
  202.     /* per dischi da 720K voglio usare un formato non ottenibile dalla DIBadMount, 
  203.     per gli altri voglio evitare la caratteristica del System 7 che accetta anche
  204.     dischi con settori difettosi, quindi devo fare tutto da solo, compreso un dialogo 
  205.     possibilmente simile a quello standard
  206.     -- 720K disks can't be obtained by DIBadMount. Other formats can, but System 7
  207.     may return a noErr code for disks with bad sectors, marking them in the allocation
  208.     table, hence it's better to avoid DIBadMount in any case. However, the user
  209.     will feel better if my dialog looks like the standard disk initialization dialog
  210.     */
  211.  
  212. invalid_buffers();
  213. if( di.supports_720K){
  214.     di.format_index=di.supports_720K;    /* format_index contains the value for 800k, the
  215.         maximum size, but I don't want that format */
  216.     di.max_format=1440;
  217.     }
  218.  
  219. SetCursor(&arrow);
  220. /* procurati l'icona da mettere nel dialogo*/
  221. ParamBlock.ioRefNum=-5;                  /*.SONY driver*/
  222. ParamBlock.ioVRefNum=drive_number;
  223. ParamBlock.csCode=21;                    /* Return Physical Drive Icon */
  224. /*ParamBlock.ioCompletion=NULL; no, non serve se la chiamata Å sincrona */
  225. icon_handle=NewHandle(128);        /* la routine ritorna un Ptr, ma PlotIcon vuole 
  226.                     un handle e la Apple sconsiglia vivamente di crearsi un handle 
  227.                     senza passare per NewHandle...
  228.                     -- I get a Ptr, but PlotIcon needs an handle and Apple discourages
  229.                     to create an handle without calling NewHandle, that could crash
  230.                     the machine, hence I must create a legal handle and copy the data
  231.                     */
  232. if( PBControlSync(&ParamBlock) != noErr)
  233.     fillmem(*icon_handle,0,128);
  234. else
  235.     mcopy(*icon_handle, *((Ptr*)&ParamBlock.csParam[0]), 128);
  236.  
  237. /* crea e posiziona il dialogo */
  238. dHandle = (DialogTHndl)Get1Resource('DLOG',132);
  239. if (dHandle) {
  240.     char buff[8];
  241.     HLock((Handle)dHandle);
  242.     PositionDialog( &((**dHandle).boundsRect));
  243.     myDialog=GetNewDialog(132,NULL,-1L);
  244.     if(in_Italia){
  245.         short    kind;
  246.         Handle    h;
  247.         Rect    r;
  248.         GetDItem(myDialog,1,&kind,&h,&r);
  249.         SetCTitle(h,di.is_not_initialized?"\pEspelli":"\pAnnulla");
  250.         GetDItem(myDialog,2,&kind,&h,&r);
  251.         SetCTitle(h,"\pInizializza");
  252.         }
  253.     else if(di.is_not_initialized){
  254.         short    kind;
  255.         Handle    h;
  256.         Rect    r;
  257.         GetDItem(myDialog,1,&kind,&h,&r);
  258.         SetCTitle(h,"\pEject");
  259.         }
  260.     my_itoa((long)(di.max_format>>1),&buff);
  261.     c2pstr(buff);
  262.     if(di.is_not_initialized)
  263.         ParamText(in_Italia ? "\pDisco non inizializzato, verrê inizializzato a " :
  264.             "\pUninitialized disk, it will be initialized at ",
  265.             buff,"\p Kbytes",PNS);
  266.     else
  267.         ParamText(in_Italia ? "\pIl disco verrê inizializzato\ra " :
  268.             "\pThis disk will be initialized\rat ", buff,"\p Kbytes",PNS);
  269.  
  270.     ModalDialog(icon_update,&item);
  271.  
  272.     if(item!=2){
  273.         if(di.is_not_initialized) diskEject();
  274.         }
  275.     else{
  276.         int     *IPtr;
  277.         GrafPtr    savePort;
  278.         static Rect rectScritta={0,54,40,300};    /* abbondare non nuoce */
  279.         GetPort( &savePort );    
  280.         SetPort(myDialog);
  281.         for(item=1;item<=3;item++){
  282.             short    kind;
  283.             Handle    h;
  284.             Rect    r;
  285.             GetDItem(myDialog,item,&kind,&h,&r);
  286.             InsetRect(&r,-4,-4);
  287.             EraseRect(&r);
  288.             }
  289.         MoveTo(64,20);
  290.         DrawString(in_Italia ? "\pInizializzazione..." :"\pInitializing...");
  291.         PlotIcon(&iconRect,icon_handle);    /* ci fosse un update non servito...*/
  292.         SetCursor(&waitCursor);
  293.  
  294.         {CntrlParam parblk;
  295.         char*pt=&parblk.csParam;
  296.         parblk.ioRefNum=-5;                  /*.SONY driver*/
  297.         parblk.ioVRefNum=drive_number;
  298.         parblk.csCode=9;                    /* Track Cache Control */
  299.         pt[0]=0;                    /* disable */
  300.         pt[1]=-1;                    /* remove */
  301.         PBControlSync(&parblk);
  302.         }
  303.  
  304.         ParamBlock.ioRefNum=-5;                    /*.SONY driver*/
  305.         ParamBlock.ioVRefNum=drive_number;        /*1 for internal -- 2 for external drive*/
  306.         ParamBlock.csCode=6;                    /*Format control code*/
  307.         IPtr= (int*)&ParamBlock.csParam;           /*point to it; pretend it's an int */
  308.         *IPtr=di.format_index;                        /* see TN 272 */
  309.  
  310.         FlushVol(PNS,drive_number);
  311.         di.disk_code=noMacDskErr;
  312.         err=PBControlSync(&ParamBlock);
  313.  
  314.         {CntrlParam parblk;
  315.         char*pt=&parblk.csParam;
  316.                 /* the initialization has changed the content of the disk,
  317.                 but the content of the track cache are NOT automatically
  318.                 invalidated, at least not always (it's not random, since when it
  319.                 happens it happens regularly, but I've not found any cause for 
  320.                 that) hence I disable the track cache, do a write to be sure,
  321.                 and enable it again. I do not guarantee that it's OK now, since
  322.                 when it does not happen it does not happen regularly, and I
  323.                 can't do hundreds of formatting just to verify...*/
  324.  
  325.         fillmem(disk_buffer,0xF6,512);
  326.         write_sectors(0,disk_buffer,1);
  327.         parblk.ioRefNum=-5;                  /*.SONY driver*/
  328.         parblk.ioVRefNum=drive_number;
  329.         parblk.csCode=9;                    /* Track Cache Control */
  330.         pt[0]=1;            /* enable */
  331.         pt[1]=1;            /* install */
  332.         PBControlSync(&parblk);
  333.         }
  334.  
  335.         if(err==noErr){
  336.  
  337.             EraseRect(&rectScritta);
  338.             MoveTo(64,20);
  339.             DrawString(in_Italia ? "\pVerifica..." :"\pVerifying...");
  340.             if(DIVerify(drive_number) == noErr){
  341.                 if(make_dir){
  342.                     EraseRect(&rectScritta);
  343.                     MoveTo(64,20);
  344.                     DrawString(in_Italia ? "\pCreazione catalogo..." :"\pCreating directory...");
  345.                     di.disk_code=DIZero (drive_number,di.max_format==1440 ? "\p720 Kbytes volume" :
  346.                         "\pUntitled");
  347.                     FlushVol (PNS,drive_number);    /* contro le stranezze del system 7 che spesso lo
  348.                         richiede immediatamente dopo averlo espulso */
  349.                     UnmountVol(NULL,drive_number);
  350.                     }
  351.                 }
  352.             else{
  353.                 beep_in_foreground();
  354.                 printf(in_Italia ? "Verifica fallita\n":"Verification failed\n");
  355.                 diskEject();
  356.                 }
  357.             }
  358.         else{
  359.             beep_in_foreground();
  360.             printf(in_Italia?"Inizializzazione fallita\n":"Initialization failed\n");
  361.             diskEject();
  362.             }
  363.         SetPort(savePort);
  364.         SetCursor(&arrow);
  365.         }
  366.     HUnlock ((Handle)dHandle);
  367.     DisposDialog(myDialog);
  368.     /*update_console();*/
  369.     DisposHandle(icon_handle);
  370.     }
  371. }
  372.  
  373.  
  374. /************** testa stato ************/
  375.  
  376. short testa_stato(inPlace,verbose)
  377. /* calls the device driver to get informations about the current disk,
  378. then does some testing for useful data that the driver does not know;
  379. informations are returned in inPlace and the global variables di.is_write_protected,
  380. sectors_on_floppy , di.is_not_initialized, di.os (useful for any disk),
  381. di.max_format, di.format_index, di.supports_720K (useful only if the disk
  382. need be initialized)
  383. */
  384.  
  385. short *inPlace;
  386. Boolean verbose;
  387. {
  388. int i;
  389. OSErr err;
  390. DrvSts status;
  391. char sector_buffer[512];
  392.  
  393. i=5;
  394. do{    /* vedi get_format sul perchÄ faccio questo */
  395.     err=DriveStatus(drive_number,&status);
  396.     if(err) read_one_sector(0,sector_buffer,drive_number);
  397.     }
  398. while(--i && err!=noErr);
  399. if(err){
  400.     if(verbose){
  401.         start_of_line();
  402.         printf("Disk drive error %d\n",err);
  403.         }
  404.     return -1;
  405.     }
  406. di.is_write_protected=status.writeProt;
  407. *inPlace=status.diskInPlace;
  408.  
  409. err=get_format(&status,sector_buffer);
  410. if(err!=noErr){
  411.     if(verbose) printf("Disk driver error\n");
  412.     return -1;
  413.     }
  414.  
  415. /* discover if the disk is not initialized: there is not a device driver call
  416. for this purpose, but that range of errors is typical for non-initialized disks */
  417.  
  418. read_one_sector(2,sector_buffer,drive_number); 
  419. if(    (di.is_not_initialized = err_code<=-66 && err_code>=-71) ){
  420.     di.os=unknown_os;
  421.     di.disk_code=ioErr;
  422.  
  423.     if(sectors_on_floppy==800){
  424.         sectors_on_floppy=1600;
  425.         if(verbose) printf(in_Italia?"Disco non inizializzato da 400/800/720 Kbytes\n":
  426.             "400/800/720 Kbytes disk, not initialized\n");
  427.         }
  428.     else if(verbose)
  429.         printf(in_Italia?"Disco non inizializzato da %ld Kbytes\n":
  430.             "%ld Kbytes disk, not initialized\n",(long)sectors_on_floppy>>1);
  431.  
  432.     return 0;
  433.     }
  434. if(err_code!=noErr) read_one_sector(2,sector_buffer,drive_number); 
  435. if(err_code){
  436.     printf("Disk read error %d\n",err_code);
  437.     di.disk_code=err_code;
  438.     di.os=unknown_os;
  439.     return noErr;
  440.     }
  441.  
  442. di.os=riconosci_disco_mac(sector_buffer);
  443. if(di.os==unknown_os){
  444.     di.disk_code=noMacDskErr;
  445.     if(is_msdos_disk(drive_number) ){
  446.         di.os=msdos;
  447.         if(verbose){
  448.             one_empty_line();
  449.             printf(in_Italia?"Questo Å un disco MS-DOS da %ldK\n":
  450.                 "MS-DOS %ldK disk\n",(long)sectors_on_floppy>>1);
  451.             }
  452.         }
  453.     else if(verbose){
  454.         one_empty_line();
  455.         printf(in_Italia?"Disco da %ldK\n":"%ldK disk\n", (long)sectors_on_floppy>>1);
  456.         }
  457.     }
  458. else{
  459.     di.disk_code=noErr;
  460.     if(verbose){
  461.         one_empty_line();
  462.         printf(in_Italia ? "Questo Å un disco Macintosh da %ldK\n" :
  463.             "Macintosh %ldK disk\n", (long)sectors_on_floppy>>1);
  464.         }
  465.     }
  466.  
  467. return noErr;
  468. }
  469.  
  470. Boolean is_wrprot()
  471. /* sometimes the write protected information is not correct, being the state
  472. of the previously inserted disk rather than the current one. Asking the 
  473. information a second time usually returns the correct value */
  474. {
  475. if(di.is_write_protected){    /* try again */
  476.     DrvSts status;
  477.     DriveStatus(drive_number,&status);
  478.     di.is_write_protected=status.writeProt;
  479.     }
  480. return di.is_write_protected;
  481. }
  482.  
  483. static OSErr get_format(status,buffer)
  484. DrvSts*status;
  485. char*buffer;    /* only to be used, it does not carry any information, but
  486.                 why allocate another buffer ? */
  487. {
  488. /* cerca il formato del disco attualmente nel drive; ritorna noErr se l'ha trovato,
  489. oppure il codice di errore ritornato dal device driver .Sony; poi, -1 se nessun
  490. formato Å quello del disco corrente (disco assente ?). Nella variabile
  491. sectors_on_floppy lascia il numero di settori, valido solo per noErr; comunque
  492. aggiorna supports_720K;
  493. -- uses the new status calls to get informations about the current disk: it 
  494. may return the error code given by PBStatus, or noErr if succeeded, or -1
  495. if none of the supported disk formats is marked as being that of the current disk;
  496. supports_720K is adjusted in any case.
  497. */
  498. long tabella[12];
  499. CntrlParam parblk;
  500. int j;
  501. OSErr err;
  502.  
  503. /* a volte succede che inserisco il disco quasi insieme all'emissione del
  504. comando da men¥, il disco viene espulso ma NON da parte della diskEject che libera
  505. il drive, ma da parte del chiamante che si vede ritornare -1 da testa_stato,
  506. perchÄ la PBStatus ritorna offLinErr. Unica soluzione, fare una read appena
  507. prima, e certo riprovare pi¥ volte aiuta
  508. */
  509. j=5;
  510. do{
  511.     fillmem(&(parblk.qLink),0,sizeof(CntrlParam));
  512.     parblk.ioRefNum=-5;
  513.     parblk.ioVRefNum=drive_number;
  514.     parblk.csCode=6;
  515.     parblk.csParam[0]=6;    /* dim tabella */
  516.  
  517.     *(long*)(&(parblk.csParam[1])) = (long)&(tabella[0]);
  518.     err=PBStatusSync (&parblk.qLink);
  519.  
  520.      /*dp("err =%d(%d)\n",err,drive_number);*/
  521.     if(err==offLinErr) read_one_sector(0,buffer,drive_number);
  522.     }
  523. while(err==offLinErr&&--j);
  524. di.supports_720K=0;
  525.  
  526. if(err==statusErr){        /* non c'Å una versione recente del device driver,
  527.             ma allora non supporta i SuperDrive e i formati possibili sono questi:
  528.             -- the device driver does not support the new status calls, but
  529.             old drivers don't support SuperDrives and DriveStatus suffices to
  530.             build the informations I need
  531.             */
  532.     sectors_on_floppy= (status->twoSideFmt==-1) ? 1600 : 800;
  533.     if(status->sides&0x80){
  534.         di.max_format=1600;
  535.         di.format_index=2;
  536.         }
  537.     else{
  538.         di.max_format=800;
  539.         di.format_index=1;
  540.         }
  541.     return noErr;
  542.     }
  543. else if(err != noErr)
  544.     return err;
  545.  
  546. sectors_on_floppy=0;
  547. /*di.format_index=0;*/
  548. di.max_format=-1;
  549. for(j=0;j<parblk.csParam[0];j++){
  550.     if(tabella[j+j+1] & 0x40000000L)    /* bit "current disk has this format" */
  551.         sectors_on_floppy=tabella[j+j];
  552.     if(tabella[j+j]==1440) di.supports_720K=j+1;
  553.     if(tabella[j+j]>di.max_format){
  554.         di.max_format=tabella[j+j];
  555.         di.format_index=j+1;
  556.         }
  557.     }
  558. /*sectors_on_floppy=100;    /*per le prove multivolume, mica voglio perdere tempo!
  559.                             -- for debugging multivolume formats, put few data
  560.                             on each disk, otherwise the tests will last hours ! */
  561. if(sectors_on_floppy==0) return -1;
  562. return noErr;
  563. }
  564.  
  565.  
  566. void identifica_hardware()
  567. /* get informations about the .Sony device driver and the disk drives  */
  568. {
  569. /* i 4 LSB di parblk.csParam[1] valgono:
  570. -- from TN272: the four LSB of parblk.csParam[1] are coded as follows:
  571. 0    no such drive
  572. 1    unspecified drive
  573. 2    400K Sony
  574. 3    800K Sony
  575. 4    SuperDrive (400K/800K GCR, 720K/1440K MFM)
  576. 5    reserved
  577. 6    reserved
  578. 7    Hard Disk 20
  579. 8-15    reserved
  580.  
  581. anyway, since in the News somebody tells that Apple is going to put out
  582. a new floppy disk drive (maybe 2.88M, maybe a floptical 20M), suntar
  583. accepts 5 as a SuperDrive-compatible disk: there is no reason why Apple
  584. should not use that code nor make that drive SuperDrive-incompatible
  585. */
  586. CntrlParam parblk;
  587. int i,n_drives=0;
  588. n_superdrives=0;
  589. last_drive=0;
  590. for (i=1;i<=max_drive;i++){        /* ci possono essere buchi, ma comunque mai oltre l'unitê 4 ! 
  591.                         -- a Macintosh can't go beyond unit 4, but there may be
  592.                         an hole since old systems assigned 3 to an external drive even 
  593.                         if unit 2 was not present
  594.                         */
  595.     drive_type[i-1]=0;
  596.     parblk.ioRefNum=-5;
  597.     parblk.ioVRefNum=i;
  598.     parblk.csCode=23;
  599.  
  600.     err_code=PBControlSync (&(parblk.qLink));
  601.     /*printf("%d %x %d\n",i,parblk.csParam[1],err_code);*/
  602.     if(err_code==controlErr){    /* una versione del disk driver anteriore a quella
  603.                                 che gestisce i SuperDrive
  604.                                 -- an old version of the device driver: get 
  605.                                 informations from DriveStatus
  606.                                 */
  607.         DrvSts status;
  608.         err_code=DriveStatus(drive_number,&status);    /* per sapere se il drive esiste */
  609.         if(err_code==noErr && status.installed>=0){
  610.             if(n_superdrives==0) preferred_drive=i;
  611.             last_drive=i;
  612.             n_drives++;
  613.             drive_type[i-1]= (status.sides&0x80) ? TWO_SIDED|0x8000 : SINGLE_SIDED|0x8000;
  614.             }
  615.         }
  616.     else if(err_code==noErr){    /* OK, puÿ essere un SuperDrive */
  617.         int j;
  618.         drive_type[i-1]=parblk.csParam[1]&0x7FFF;
  619.         j= parblk.csParam[1] &0xF;
  620.         if(j==SUPERDRIVE || j==SUPERDRIVE+1){
  621.             preferred_drive=i;
  622.             n_superdrives++;
  623.             }
  624.         if(n_superdrives==0) preferred_drive=i;
  625.         last_drive=i;
  626.         n_drives++;
  627.         }
  628.     }
  629.  
  630. if(n_superdrives>1 || n_superdrives==0&&n_drives>1)
  631.     preferred_drive=0;
  632.  
  633.  
  634. #if 0        /* no more useful, since now I do my own buffering */
  635. if(preferred_drive){
  636.     parblk.ioRefNum=-5;                  /*.SONY driver*/
  637.     parblk.ioVRefNum=preferred_drive;
  638.     parblk.csCode=9;                    /* Track Cache Control */
  639.     *(short*)&parblk.csParam =1*256+1;    /* Track cache on: pare che sia la normalitê, 
  640.                                         ma non si sa mai
  641.                                         -- track cache on: suntar is much faster. 
  642.                                         Really, that's the default mode on our Mac,
  643.                                         but we don't know about other Macs. Well, in
  644.                                         theory one should restore the original situation
  645.                                         when quitting, but there seems to be no easy
  646.                                         way to know which was the current setting:
  647.                                         "When the cache is removed, 680x0 register D0 
  648.                                         contains the previous size of the cache", 
  649.                                         (TN 272) but that does NOT work !, in D0
  650.                                         it always return 0 for noError, looking at D0.L,
  651.                                         D1.L and A0.L does not yield any number that
  652.                                         could be that thing
  653.                                         */
  654.  
  655.     PBControlSync(&parblk);
  656.     }
  657. #endif
  658.  
  659. if(n_superdrives==0 && !accetta_GCR){
  660.         ParamText(in_Italia ?
  661. "\pNon hai un SuperDrive, quindi non potrai\rleggere dischi scritti su un sistema UNIX":
  662. "\pYou have no SuperDrive, you can\'t read\rdisks written on an UNIX machine",
  663.         PNS,PNS,PNS );
  664.         my_alert();
  665.     }
  666.  
  667. }
  668.  
  669. /******************* buffering *********************************/
  670.  
  671. /* suntar either writes or reads, and when it does neither of the two
  672. it's better to flush the buffers anyway, since the disk could be ejected
  673. without letting him know. Hence it's better to let the buffer empty even
  674. in cases when the data is still good. Otherwise, this is a simple
  675. implementation of a write-back cache, consisting of a single "cache line" with
  676. status information for each sector.
  677.  
  678. Probably it would be faster using Async calls, but that's more difficult,
  679. and an old Apple Technical Note told that the first versions of MultiFinder
  680. did not let an application go to background while it had some Async calls
  681. pending.
  682. Really, in many cases the best thing would be to launch one independent Async
  683. call for each sector, so the operation will start as sooner as possible,
  684. with the highest degree of parallelism. But that's even more difficult and
  685. might cause more risks for incompatibility; and is the Mac hardware and software
  686. able to exploit that potential parallelism, or is everything serialized anyway ?.
  687. */
  688.  
  689.  
  690. short floppy_buffer_size;
  691.  
  692. static char* buffers_base;
  693. static sector_t first_in_buffer;
  694. static enum{empty, full, dirty };
  695. static char  *buffer_state;
  696. static Boolean traccia_difettosa;
  697.  
  698. void invalid_buffers(void);
  699. void invalid_buffers()
  700. {
  701. short i;
  702. for(i=0;i<floppy_buffer_size;i++)
  703.     buffer_state[i]=empty;
  704. first_in_buffer= -floppy_buffer_size;
  705. traccia_difettosa=false;
  706. }
  707.  
  708. void invalid_after(start_sector)
  709. sector_t start_sector;
  710. {
  711. short i;
  712. for(i=0;i<floppy_buffer_size;i++)
  713.     if(first_in_buffer+i >= start_sector) buffer_state[i]=empty;
  714. }
  715.  
  716.  
  717. void init_buffering()
  718. {
  719. ResrvMem ((Size)floppy_buffer_size);
  720. buffer_state=NewPtr((Size)floppy_buffer_size);
  721. invalid_buffers();
  722. buffers_base=NewPtr((Size)floppy_buffer_size*512);
  723. check_allocated(buffers_base);
  724. }
  725.  
  726. void check_allocated(p)
  727. void *p;
  728. {
  729. if(!p){
  730.     ParamText("\pCan\'t allocate disk buffers\rReduce their size or increase the partition",
  731.         PNS,PNS,PNS);
  732.     my_alert();
  733.     ExitToShell();
  734.     }
  735. }
  736.  
  737. void flush_buffers()
  738. {
  739. short primo=0, ultimo;
  740.  
  741. /*int i;for(i=0;i<floppy_buffer_size;i++)
  742.     printf("%d ",buffer_state[i]);
  743. printf("\n"); */
  744.  
  745. err_code=noErr;
  746. while(primo<floppy_buffer_size){
  747.     while(buffer_state[primo]!=dirty && primo<floppy_buffer_size) primo++;
  748.     if(primo>=floppy_buffer_size) break;
  749.     ultimo=primo+1;
  750.     while(ultimo<floppy_buffer_size && buffer_state[ultimo]==dirty ) ultimo++;
  751.     /*dp("write %ld,%ld\n",(long)(first_in_buffer+primo),(long)(first_in_buffer+ultimo-1));*/
  752.     write_sectors(first_in_buffer+primo,buffers_base+((sector_t)primo<<9),ultimo-primo);
  753.     if(err_code){
  754.         /*dp("errore, riprovo\n");*/
  755.         write_sectors(first_in_buffer+primo,buffers_base+((sector_t)primo<<9),ultimo-primo);
  756.         if(err_code){
  757.             invalid_buffers();
  758.             return;
  759.             }
  760.         }
  761.     if(verify_writes){
  762.         verify_sectors(first_in_buffer+primo,buffers_base+((sector_t)primo<<9),ultimo-primo);
  763.         if(err_code){
  764.             start_of_line();
  765.             printf("Write/verify: verification failed (sector");
  766.             if(primo==ultimo-1)
  767.                 printf(" %ld)\n",(long)(first_in_buffer+(long)primo));
  768.             else
  769.                 printf("s %ld to %ld)\n",(long)(first_in_buffer+(long)primo),
  770.                     first_in_buffer+(long)ultimo-1);
  771.             invalid_buffers();
  772.             raise_error();
  773.             }
  774.         }
  775.     primo=ultimo;
  776.     }
  777. invalid_buffers();
  778. }
  779.  
  780. Boolean dirty_buffers()
  781. {
  782. short i;
  783. for(i=0;i<floppy_buffer_size;i++)
  784.     if(buffer_state[i]==dirty) return true;
  785. return false;
  786. }
  787.  
  788. void leggi_settore(n_sect,buffer)
  789. sector_t n_sect;
  790. char *buffer;
  791. {
  792. char *pos_in_buffer;
  793.  
  794. if(n_sect>=first_in_buffer && n_sect<first_in_buffer+floppy_buffer_size){    /* match */
  795.     pos_in_buffer = buffers_base+((n_sect-first_in_buffer)<<9);
  796.  
  797.     if( buffer_state[n_sect-first_in_buffer]!=empty){
  798. /*dp("match lettura %ld\n",n_sect);*/
  799.         mcopy(buffer,pos_in_buffer,512);
  800.         err_code=noErr;
  801.         return;
  802.         }
  803.     if(traccia_difettosa){        /* defective sector on the track... */
  804.         read_sectors(n_sect, pos_in_buffer, 1);
  805.         mcopy(buffer,pos_in_buffer,512);
  806.         if(!err_code) buffer_state[n_sect-first_in_buffer]=full;
  807.         return;
  808.         }
  809.     }
  810.  
  811. flush_buffers();
  812. /* invalid_buffers(); */
  813.  
  814. traccia_difettosa=false;
  815. first_in_buffer= n_sect - n_sect%floppy_buffer_size;
  816. pos_in_buffer= buffers_base+((n_sect-first_in_buffer)<<9);
  817.  
  818. if(fase==reading_disk && ! listonly || n_sect<=2){    /* sectors 0 and 2 are read
  819.         many times, it's better to read all of them even during a List */
  820.     short n_to_read;
  821. /*dp("leggo multiplo %ld\n",n_sect);*/
  822.     if(first_in_buffer+floppy_buffer_size<=sectors_on_floppy)
  823.         n_to_read= floppy_buffer_size;
  824.     else
  825.         n_to_read=sectors_on_floppy-first_in_buffer;
  826.     read_sectors(first_in_buffer,buffers_base,n_to_read);
  827.     if(! err_code){
  828.         short i;
  829.         for(i=0;i<n_to_read;i++)
  830.             buffer_state[i]=full;
  831.         for(;i<floppy_buffer_size;i++)
  832.             buffer_state[i]=empty;
  833.         mcopy(buffer,pos_in_buffer,512);
  834.         return;
  835.         }
  836.     traccia_difettosa=true;
  837.     }
  838.  
  839. /*dp("leggo singolo %ld\n",n_sect);*/
  840. read_sectors(n_sect, pos_in_buffer, 1);
  841. mcopy(buffer,pos_in_buffer,512);
  842. if(!err_code) buffer_state[n_sect-first_in_buffer]=full;return;
  843. }
  844.  
  845. void scrivi_settore(n_sect,buffer)
  846. sector_t n_sect;
  847. char *buffer;
  848. {
  849. if(n_sect<first_in_buffer || n_sect>=first_in_buffer+floppy_buffer_size ){
  850. /*dp("chiedo flush %ld\n",n_sect);*/
  851.     flush_buffers();
  852.     if(err_code) return;
  853.     /* invalid_buffers(); */
  854.     first_in_buffer= n_sect - n_sect%floppy_buffer_size;
  855.     }
  856. /*else dp("match write %ld\n",n_sect);*/
  857. mcopy(buffers_base+((n_sect-first_in_buffer)<<9),buffer,512);
  858. buffer_state[n_sect-first_in_buffer]=dirty;
  859. err_code=noErr;
  860. return;
  861. }
  862.  
  863. /************** assembly language *******************************/
  864.  
  865.  
  866. /* from Inside Macintosh volume II page 216 */
  867.  
  868.  
  869. void diskEject()    /* ho il sospetto si riesca a fare anche ad alto livello,
  870.                     dovrebbe essere permesso passare un drive number al posto 
  871.                     di vRefNum
  872.                     -- probably it can be done in C */
  873. {
  874. ultimo_disco_espulso=true;
  875. disco_espulso=true;
  876. flush_buffers();
  877. if(drive_number==0) return;
  878.     asm{
  879.         moveq    #31,D0  /* #<ioVQElSize/2>-1,D0 */
  880. clearloop:
  881.         clr.w    -(SP)
  882.         dbra    D0,@clearloop
  883.         move.l    SP,A0
  884.         move.w    #-5,0x18(A0)    /* #-5,ioRefNum(A0) */
  885.         move.w    drive_number,0x16(A0)        /* drive_number,ioDrvNum(A0) */
  886.         move.w    #7,0x1A(A0)        /* #ejectCode,csCode(A0) */
  887.         dc.w 0xA017                /* _Eject */
  888.         add.w    #0x40,SP        /* #ioVQElSize,SP */
  889.     }
  890. drive_number=0;
  891. }
  892.  
  893. /**********************************/
  894. void read_sectors(sect_n,buffer,n_sectors)
  895. int n_sectors;
  896.  
  897. sector_t sect_n;
  898. char *buffer;
  899. {
  900. long count;
  901.  
  902. if(file_aperto){
  903.     /* if working from a file rather than a disk... */
  904.     err_code=0;
  905.     if(sect_n!=file_current_s)
  906.         err_code=SetFPos(inputFile,fsFromStart,(long)sect_n<<9);
  907.     if(err_code==eofErr)
  908.         err_code=sectNFErr;        /* sector not found error */
  909.     else if(!err_code){
  910.         count=(long)n_sectors<<9;
  911.         err_code=FSRead(inputFile,&count,buffer);
  912.         if(!err_code && !count) err_code=eofErr;
  913.         if(err_code==eofErr && count!=0){
  914.             fillmem(&buffer[count],0,(n_sectors<<9)-(int)count);
  915.             err_code=noErr;
  916.             }
  917.         }
  918.     if(err_code)
  919.             file_current_s=-1;
  920.     else
  921.             file_current_s=sect_n+n_sectors;
  922.     return;
  923.     }
  924.  
  925. asm{
  926.     moveq    #24,D0             /* #<ioQElsize/2>-1,D0 */
  927. clrloop:    
  928.     clr.w    -(SP)
  929.     dbra    D0,@clrloop
  930.     move.l    SP,A0
  931.     move.w    #-5,0x18(A0)    /* #-5,ioRefNum(A0) */
  932.     move.w    drive_number,0x16(A0)        /* drive_number,ioDrvNum(A0) */
  933.     move.w    #1,0x2C(A0)        /* #1,ioPosMode(A0) absolute positioning */
  934. #if SECTOR_T_SIZE==4
  935.     move.l    sect_n,D0
  936.     lsl.l    #4,D0            /* 9 is too big... */
  937.     lsl.l    #5,D0
  938. #else
  939.     move.w    sect_n,D0
  940.     mulu    #512,D0            /* does both int->long conversion and shift */
  941. #endif
  942.     move.l    D0,0x2E(A0)        /* D0,ioPosOffset(A0) */
  943.  
  944.     move.w    n_sectors,D0
  945.     mulu    #512,D0
  946.     move.l    D0,0x24(A0)        /* D0,ioReqCount(A0)    /* read n_sectors sectors */
  947.     move.l    buffer,A1
  948.     move.l    A1,0x20(A0)        /* A1,ioBuffer(A0) */
  949.     dc.w 0xA002                /* _Read */
  950.     move.w    0x10(A0),err_code    /* ioResult(A0),err_code */
  951.     /*move.l  0x28(A0),count*/        /* ioActCount(A0),count) */
  952.     add.w    #0x32,SP        /* #ioQElSize,SP */
  953.     }
  954. }
  955.  
  956. void read_one_sector(sect_n,buffer,drive_n)
  957. /* it reads from the disk even when read_sectors is redirected to read from a file... */
  958. sector_t sect_n;
  959. char *buffer;
  960. short drive_n;
  961. {
  962. asm{
  963.     moveq    #24,D0             /* #<ioQElsize/2>-1,D0 */
  964. clrloop:    
  965.     clr.w    -(SP)
  966.     dbra    D0,@clrloop
  967.     move.l    SP,A0
  968.     move.w    #-5,0x18(A0)    /* #-5,ioRefNum(A0) */
  969.     move.w    drive_n,0x16(A0)        /* drive_number,ioDrvNum(A0) */
  970.     move.w    #1,0x2C(A0)        /* #1,ioPosMode(A0) absolute positioning */
  971. #if SECTOR_T_SIZE==4
  972.     move.l    sect_n,D0
  973.     lsl.l    #4,D0            /* 9 is too big... */
  974.     lsl.l    #5,D0
  975. #else
  976.     move.w    sect_n,D0
  977.     mulu    #512,D0            /* does both int->long conversion and shift */
  978. #endif
  979.     move.l    D0,0x2E(A0)        /* D0,ioPosOffset(A0) */
  980.  
  981.     move.l    #512,0x24(A0)
  982.     move.l    buffer,A1
  983.     move.l    A1,0x20(A0)        /* A1,ioBuffer(A0) */
  984.     dc.w 0xA002                /* _Read */
  985.     move.w    0x10(A0),err_code    /* ioResult(A0),err_code */
  986.     add.w    #0x32,SP        /* #ioQElSize,SP */
  987.  
  988.     }
  989. }
  990.  
  991.  
  992. /******************************/
  993.  
  994. void write_sectors(sect_n,buffer,n_sectors)
  995. sector_t sect_n;
  996. char *buffer;
  997. int n_sectors;
  998. {
  999. /*err_code=0;
  1000. return;*/
  1001.  
  1002. asm{
  1003.     moveq    #24,D0             /* #<ioQElsize/2>-1,D0 */
  1004. clrloop:
  1005.     clr.w    -(SP)
  1006.     dbra D0,@clrloop
  1007.     move.l    SP,A0
  1008.     move.w    #-5,0x18(A0)    /* #-5,ioRefNum(A0) */
  1009.     move.w    drive_number,0x16(A0)        /* drive_number,ioDrvNum(A0) */
  1010.     move.w    #1,0x2C(A0)        /* #1,ioPosMode(A0) absolute positioning */
  1011. #if SECTOR_T_SIZE==4
  1012.     move.l    sect_n,D0
  1013.     lsl.l    #4,D0
  1014.     lsl.l    #5,D0
  1015. #else
  1016.     move.w    sect_n,D0
  1017.     mulu    #512,D0
  1018. #endif
  1019.     move.l    D0,0x2E(A0)        /* D0,ioPosOffset(A0) */
  1020.  
  1021.     move.w    n_sectors,D0
  1022.     mulu    #512,D0
  1023.     move.l    D0,0x24(A0)        /* D0,ioReqCount(A0)    /* write n_sectors sectors */
  1024.     move.l    buffer,A1
  1025.     move.l    A1,0x20(A0)        /* A1,ioBuffer(A0) */
  1026.     dc.w 0xA003                /* _Write */
  1027.     move.w    0x10(A0),err_code    /* ioResult(A0),err_code */
  1028.     add.w    #0x32,SP        /* #ioQElSize,SP */
  1029.     }
  1030. }
  1031.  
  1032.  
  1033. static void verify_sectors(sect_n,buffer,n_sectors)
  1034. sector_t sect_n;
  1035. char *buffer;
  1036. int n_sectors;
  1037. {
  1038. asm{
  1039.     moveq    #24,D0             /* #<ioQElsize/2>-1,D0 */
  1040. clrloop:    
  1041.     clr.w    -(SP)
  1042.     dbra    D0,@clrloop
  1043.     move.l    SP,A0
  1044.     move.w    #-5,0x18(A0)    /* #-5,ioRefNum(A0) */
  1045.     move.w    drive_number,0x16(A0)        /* drive_number,ioDrvNum(A0) */
  1046.     move.w    #65,0x2C(A0)        /* #1+64,ioPosMode(A0) absolute positioning &
  1047.                                 read/verify */
  1048. #if SECTOR_T_SIZE==4
  1049.     move.l    sect_n,D0
  1050.     lsl.l    #4,D0            /* 9 is too big... */
  1051.     lsl.l    #5,D0
  1052. #else
  1053.     move.w    sect_n,D0
  1054.     mulu    #512,D0            /* does both int->long conversion and shift */
  1055. #endif
  1056.     move.l    D0,0x2E(A0)        /* D0,ioPosOffset(A0) */
  1057.  
  1058.     move.w    n_sectors,D0
  1059.     mulu    #512,D0
  1060.     move.l    D0,0x24(A0)        /* D0,ioReqCount(A0)    /* read n_sectors sectors */
  1061.     move.l    buffer,A1
  1062.     move.l    A1,0x20(A0)        /* A1,ioBuffer(A0) */
  1063.     dc.w 0xA002                /* _Read */
  1064.     move.w    0x10(A0),err_code    /* ioResult(A0),err_code */
  1065.     add.w    #0x32,SP        /* #ioQElSize,SP */
  1066.  
  1067.     }
  1068. }