home *** CD-ROM | disk | FTP | other *** search
/ Computer Club Elmshorn Atari PD / CCE_PD.iso / pc / 0600 / CCE_0646.ZIP / CCE_0646.PD / MFS606S / MINIXFS / HDIO.C < prev    next >
C/C++ Source or Header  |  1993-07-24  |  10KB  |  446 lines

  1. #include "pun.h"
  2. #include "xhdi.h"
  3.  
  4. #include <string.h>
  5.  
  6. #ifdef MFS_XFS
  7. #include "minixfs.h"
  8. #include "global.h"
  9. #define XRWABS RWABS
  10. #define DWARN(mes,drive) ALERT("Drive %c: " mes,drive)
  11. #else
  12. #define DWARN(mes,drive) fprintf(stderr,"Drive %c: " mes "\n",drive)
  13. #define ALERT(x)     fprintf(stderr,x "\n")
  14. #define NEED_SUPER
  15. #define RWABS Rwabs
  16. #define Kmalloc malloc
  17. #define Kfree free
  18. #define GETBPB Getbpb
  19. #include <osbind.h>
  20. #include <alloc.h>
  21. #include <stdio.h>
  22. #include "hdio.h"
  23.  
  24. #define XRWABS(a,b,c,d,e,f) \
  25. trap_13_wwlwwwl((short)(0x04),(short)(a),(long)(b),(short)(c),(short)(d)\
  26. ,(short)(e),(long)(f) )
  27.  
  28. #define trap_13_wwlwwwl(n, a, b, c, d, e, f)                \
  29. ({                                    \
  30.     register long retvalue __asm__("d0");                \
  31.     volatile short _a = (volatile short)(a);            \
  32.     volatile long  _b = (volatile long) (b);            \
  33.     volatile short _c = (volatile short)(c);            \
  34.     volatile short _d = (volatile short)(d);            \
  35.     volatile short _e = (volatile short)(e);            \
  36.     volatile long  _f = (volatile long) (f);            \
  37.                                         \
  38.     __asm__ volatile                        \
  39.     ("\
  40.         movl    %5,sp@-; \
  41.         movw    %4,sp@-; \
  42.         movw    %3,sp@-; \
  43.         movw    %2,sp@-; \
  44.         movl    %1,sp@-; \
  45.         movw    %0,sp@-    "                    \
  46.     :                          /* outputs */    \
  47.     : "r"(_a), "r"(_b), "r"(_c), "r"(_d), "r"(_e), "r"(_f) /* inputs  */ \
  48.     );                                \
  49.                                     \
  50.     __asm__ volatile                        \
  51.     ("\
  52.         movw    %1,sp@-; \
  53.         trap    #13;    \
  54.         addw    #18,sp "                    \
  55.     : "=r"(retvalue)            /* outputs */        \
  56.     : "g"(n)                /* inputs  */        \
  57.     : "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */    \
  58.     );                                \
  59.     retvalue;                            \
  60. })
  61.  
  62. #endif
  63.  
  64. /* List of error codes for get_hddinf */
  65.  
  66. char *hdd_err[] = { 
  67. "OK",
  68. "Bad BPB on floppy drive",
  69. "Need drive A-P for PUN_INFO",
  70. "Invalid or no PUN_INFO structure",
  71. "Invalid drive",
  72. "Physical mode disabled for ICD software",
  73. "Physical lrecno error",
  74. "XHInqDev2 failed (old XHDI version?) and bad BPB",
  75. "XHInqDev failed",
  76. "Unrecognised partition id",
  77. "XHInqTarget failed",
  78. "Unsupported physical sector size" };
  79.  
  80.  
  81. /*
  82.  * Hard disk info. This is a general purpose routine to handle minixfs' needs
  83.  * for hard disks. If this function returns non-zero then the partition 
  84.  * cannot be accessed. XHDI and pun_info are used to get partition info.
  85.  * The structure 'hdinf' is filled in as approproiate.
  86.  *
  87.  * If this looks awful then that's because it *is*.
  88.  */
  89.  
  90. static char rno_xhdi,try_xhdi;
  91. static char try_lrecno,rno_lrecno;
  92. static char try_plrecno,rno_plrecno;
  93.  
  94. char is_icd;
  95.  
  96. int get_hddinf(drive,hdinf,flag)
  97. int drive;
  98. struct hdinfo *hdinf;
  99. char flag;
  100. {
  101.     long ret;
  102. #ifdef NEED_SUPER
  103.     long tstack;
  104.     tstack=Super(0l);
  105.     if(!((*(long *)0x4c2) & (1l<<drive))) return 4;
  106. #endif
  107.     ret = _get_hddinf(drive,hdinf,flag);
  108. #ifdef NEED_SUPER
  109.     Super(tstack);
  110. #endif
  111.     return ret;
  112. }
  113.  
  114. int _get_hddinf(drive,hdinf,flag)
  115. int drive;
  116. struct hdinfo *hdinf; 
  117. char flag;
  118. {
  119.     _BPB *bpb;
  120.  
  121.     hdinf->major=drive;    /* May get overwritten later */
  122.  
  123.     bpb=GETBPB(drive); 
  124.     if( flag ) bpb=0;
  125.  
  126.     /* Step 1: if bpb OK and sector size 512 bytes or 1K we may get away
  127.      * with normal Rwabs.
  128.      */
  129.  
  130.     /* NBB: ICD software does something peculiar with the pun_info 
  131.      * structure. I don't know exactly what. HOWEVER it looks like
  132.      * the six bytes before pun_ptr contain the magic number 
  133.      * 'ICDB' followed by a version number. Also there are four longs
  134.      * between end of pun and partition_start elements which are all
  135.      * zeros. Anyway we look for ICDB and then reference four elements
  136.      * further up partition_start.
  137.      */
  138.     if( !bpb || (bpb->recsiz!=512 && bpb->recsiz!=1024) )
  139.     {
  140.         long tsecsiz;
  141.         char mpid[4];
  142.  
  143.         /* OK can't use normal Rwabs: try XHDI or pun_info */
  144.  
  145.         /* Bypass this rubbish for floppies */
  146.         if(drive < 2 ) return 1;
  147.  
  148.         /* Try and get info from pun_inf structure */
  149.         if( no_xhdi() )
  150.         {
  151.             struct pun_info *pinf;
  152.             char *icd_magic;
  153.             if(drive >= MAXUNITS) return 2;
  154.             if(!(*(long *)0x516)) return 3;
  155.             pinf=PUN_PTR;
  156.             icd_magic=((char *)pinf)-6;
  157.             if(!pinf || (PUN_VALID & pinf->pun[drive]) ) return 4;
  158.             hdinf->scsiz = 1;
  159.  
  160.             if(strncmp(icd_magic,"ICDB",4))
  161.                 hdinf->start = pinf->partition_start[drive];
  162.             else
  163.             {
  164.                 is_icd=1;
  165. #ifdef NO_ICD_PHYS
  166.                 return 5;
  167. #else
  168.                 hdinf->start = pinf->partition_start[drive+4];
  169. #endif
  170.             }
  171.             hdinf->size = 0;
  172.             hdinf->minor = pinf->pun[drive];
  173.             hdinf->major = (hdinf->minor & PUN_DEV) +2;
  174.             hdinf->rwmode = RW_PHYS;
  175.             /* We want to access at least first few sectors */
  176.             if(hdinf->start > 0xfff0)
  177.             {
  178.                 if(no_plrecno(hdinf->major)) return 6;
  179.                 else hdinf->rwmode |= RW_LRECNO;
  180.             }
  181.             return 0;
  182.         }
  183.  
  184.         hdinf->rwmode = RW_XHDI | RW_LRECNO;
  185.  
  186.         /* Hmmmm Getbpb failed or bad secsize: see what XHDI can do */
  187.  
  188.         if( XHInqDev2(drive,&hdinf->major,&hdinf->minor,&hdinf->start,
  189.                               0,&hdinf->size,mpid) )
  190.         {
  191.             if(!bpb) return 7;
  192.             if( XHInqDev(drive,&hdinf->major,&hdinf->minor,
  193.                             &hdinf->start,0) ) return 8;
  194.         }
  195.  
  196.         /* See if it's a recognised partition id or bpb OK*/
  197.  
  198.         if(!bpb && strcmp(mpid,"RAW") && strcmp(mpid,"MIX")) return 9;
  199.  
  200.         /* Get physical sector size */
  201.         if( XHInqTarget(hdinf->major,hdinf->minor,&tsecsiz,0,0) )
  202.                                       return 10;
  203.  
  204.         if(tsecsiz==512) hdinf->scsiz=1;
  205.         else 
  206.         {
  207.             if(tsecsiz==1024) hdinf->scsiz=0;
  208.             else return 11;
  209.         }
  210.         return 0;
  211.     }
  212.     if(bpb->recsiz==512) hdinf->scsiz=1;
  213.     else hdinf->scsiz=0;
  214.     hdinf->size=0;
  215.     hdinf->rwmode = RW_NORMAL;
  216.     return 0;
  217. }
  218.  
  219. /* This function is called after get_hddinf and is used to finalise the
  220.  * accessibility of a partition. The 'size' parameter is the size of the
  221.  * partition in K; this info will typically come from the super block of
  222.  * a filesystem. 
  223.  * Return values:
  224.  * 0    OK
  225.  * 1    Partition inaccessible.
  226.  */
  227.  
  228. int set_lrecno(hdinf,size)
  229. struct hdinfo *hdinf;
  230. long size;
  231. {
  232.  
  233.     if(hdinf->scsiz) size <<=1;
  234.     if( ( (hdinf->rwmode & RW_MODE) == RW_XHDI) && hdinf->size
  235.                                && (hdinf->size < size) )
  236.     {
  237.         DWARN("Filesystem size bigger than partition size!",
  238.                                 hdinf->major);
  239.     }
  240.     else hdinf->size = size;
  241.  
  242.     hdinf->rwmode |= RW_CHECK;
  243.  
  244.     if(hdinf->rwmode & RW_LRECNO) return 0;
  245.  
  246.     switch(hdinf->rwmode & RW_MODE)
  247.     {
  248.         case RW_NORMAL:
  249.         if(size > 0xfffe) 
  250.         {
  251.             if(no_lrecno(hdinf->major))
  252.             {
  253.             /* No logical lrecno: try forced physical mode access */
  254.                 int drive;
  255.                 drive = hdinf->major;
  256.                 if(get_hddinf(drive,hdinf,1)) return 1;
  257.                 else return (set_lrecno(hdinf,size));
  258.             }
  259.             else hdinf->rwmode |= RW_LRECNO;
  260.         }
  261.         return 0;
  262.  
  263.         case RW_PHYS:
  264.         if(size+hdinf->start >= 0xfffe)
  265.         {
  266.             if(no_plrecno(hdinf->major)) return 1;
  267.             hdinf->size = size;
  268.             hdinf->rwmode |= RW_LRECNO;
  269.         }
  270.         return 0;
  271.     }
  272.  
  273.     return 1;    /* This can't happen */
  274. }
  275.  
  276. /* Test for 'lrecno' parameter on drive 'drive': mode' is RWABS mode to use 
  277.  * (2=logical,10=physical).
  278.  * Return values:
  279.  * 0 OK
  280.  * 1 Read error.
  281.  * 2 No lrecno recognised.
  282.  * 3 Error reading large sector number (possibly OK if partition too small).
  283.  * 4 Wraparound bug present.
  284.  * 5 Allocation error.
  285.  */
  286.  
  287. int test_lrecno(drive,mode)
  288. int drive;
  289. int mode;
  290. {
  291.     char *block_buf1,*block_buf2;
  292.     int size;
  293.     _BPB *bpb;
  294.     if(mode & 8) size=1024;
  295.     else
  296.     {
  297.         bpb=GETBPB(drive);
  298.         if(!bpb) size=1024;
  299.         else size=bpb->recsiz;
  300.     }
  301.     block_buf1=Kmalloc(size<<1);
  302.     block_buf2=block_buf1+size;
  303.     bzero(block_buf1,size<<1);
  304.  
  305.     if(!block_buf1) return 5;
  306.  
  307.     /* read in boot sector */
  308.     if(RWABS(mode,block_buf1,1,0,drive)) 
  309.     {
  310.         Kfree(block_buf1);
  311.         return 1;
  312.     }
  313.  
  314.     /* read it in with lrecno */    
  315.     if( XRWABS(mode,block_buf2,1,-1,drive,0l) ) 
  316.     {
  317.         Kfree(block_buf1);
  318.         return 2;
  319.     }
  320.  
  321.     /* Compare the two */
  322.     if(bcmp(block_buf1,block_buf2,size))
  323.     {
  324.         Kfree(block_buf1);
  325.         return 2;
  326.     }
  327.  
  328.     /* read in next sector with lrecno */
  329.     if(XRWABS(mode,block_buf2,1,-1,drive,1l))
  330.     {
  331.         Kfree(block_buf1);
  332.         return 1;
  333.     }
  334.  
  335.     /* compare the two */
  336.     if(!bcmp(block_buf1,block_buf2,size))
  337.     {
  338.         Kfree(block_buf1);
  339.         return 2;
  340.     }
  341.  
  342.     /* Check for lrecno bug, this causes the upper word of a long sector
  343.      * number to be ignored. Read in sector 0 and 0x10000, if the bug is
  344.      * present then these will be identical.
  345.      */
  346.     bzero(block_buf2,size);
  347.  
  348.     if(XRWABS(mode,block_buf2,1,-1,drive,0x10000l))
  349.     {
  350.         Kfree(block_buf1);
  351.         return 3;
  352.     }
  353.     else if(!bcmp(block_buf1,block_buf2,size))
  354.     {
  355.         Kfree(block_buf1);
  356.         return 4;
  357.     }
  358.  
  359.     Kfree(block_buf1);
  360.     return 0;
  361.  
  362. }
  363.  
  364. int no_lrecno(drv)
  365. int drv;
  366. {
  367.     if( !try_lrecno )
  368.     {
  369.         rno_lrecno = test_lrecno(drv,2) ;
  370.         try_lrecno = 1;
  371.     }
  372.     return rno_lrecno;
  373. }
  374.  
  375. int no_plrecno(drv)
  376. int drv;
  377. {
  378. #ifdef NO_ICD_PHYS
  379.     if(is_icd) return 1;
  380. #endif
  381.     if( !try_plrecno ) 
  382.     {
  383.  
  384.         try_plrecno = 1;
  385.         rno_plrecno = test_lrecno(drv,10) ;
  386.     }
  387.     return rno_plrecno;
  388. }
  389.  
  390. int no_xhdi()
  391. {
  392.     if( !try_xhdi ) 
  393.     {
  394.         if( !XHGetVersion() ) rno_xhdi=1;
  395.         try_xhdi=1;
  396.     }
  397.     return rno_xhdi;
  398. }
  399.  
  400. /* 
  401.  * This is (finally!) the I/O function hdinf uses. It reads/writes in 1K chunks
  402.  * and calls the relevant functions according to the hdinf structure.
  403.  */
  404.  
  405. long block_rwabs(rw,buf,num,recno,hdinf)
  406. int rw;
  407. void *buf;
  408. unsigned num;
  409. long recno;
  410. struct hdinfo *hdinf;
  411. {
  412.     if( hdinf->scsiz )
  413.     {
  414.         recno <<=1;
  415.         num <<=1;
  416.     }
  417.  
  418.     if( (hdinf->rwmode & RW_CHECK) && (recno+num > hdinf->size) )
  419.     {
  420.         DWARN("Attempted access outside partition",hdinf->major);
  421.         return -1;
  422.     }
  423.  
  424.     switch(hdinf->rwmode & (RW_MODE|RW_LRECNO))
  425.     {
  426.         case RW_NORMAL:
  427.         return RWABS(rw,buf,num,(unsigned)recno,hdinf->major);
  428.  
  429.         case RW_NORMAL | RW_LRECNO:
  430.         return XRWABS(rw,buf,num,-1,hdinf->major,recno);
  431.  
  432.         case RW_PHYS:
  433.         return RWABS(rw | 8,buf,num,(unsigned)(recno+hdinf->start),
  434.                                   hdinf->major);
  435.  
  436.         case RW_PHYS | RW_LRECNO:
  437.         return XRWABS(rw | 8,buf,num,-1,hdinf->major,
  438.                                 recno+hdinf->start);
  439.  
  440.         case RW_XHDI | RW_LRECNO:
  441.         return XHReadWrite(hdinf->major,hdinf->minor,rw,
  442.                             recno+hdinf->start,num,buf);
  443.     }
  444.     return 1;    /* This can't happen ! */
  445. }
  446.