Advertisement
xbug

SA-cover-poc.c

Aug 3rd, 2018
469
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 22.87 KB | None | 0 0
  1. /*
  2.  
  3. This POC was developed for a Western-digital 250GB HAWK family drive (e.g. WD2500KS-??MJ??, WD2500KS-??MK? .....).
  4. It uses the unallocated reserved-areas mapped to heads 2 through 5 to store and access data.
  5.  
  6. use 'lspci -v' to find your SATA IO address, e.g:
  7.  
  8. 00:1f.2 IDE interface: Intel Corporation N10/ICH7 Family SATA Controller [IDE mode] (rev 01) (prog-if 8a [Master SecP PriP])
  9.     Subsystem: Giga-byte Technology Device b002
  10.     Flags: bus master, 66MHz, medium devsel, latency 0, IRQ 19
  11. *** I/O ports at 01f0 [size=8]
  12.     I/O ports at 03f4 [size=1]
  13. *** I/O ports at 0170 [size=8]
  14.     I/O ports at 0374 [size=1]
  15.     I/O ports at f000 [size=16]
  16.     Capabilities: [70] Power Management version 2
  17.     Kernel driver in use: ata_piix
  18.  
  19. Known issues with the POC:
  20. - The POC is desinged to work on the master drive of the specific IO port.
  21. - The code does not detect bad-sectors in the service area. If such sectors exist, the code will behave unexpectedly.
  22. - While the POC is sending Vendor Specific Commands the OS might report errors trying to communicate with the drive. In fact, it may be required to reboot the OS (or power-cycle the drive) after the POC had completed executing.
  23. - When reading the service-area into a file, the POC reads the entire area (mapped to heads 2 through 5) regardless of the size of the file written to the service-area.
  24.  
  25. We believe the OS/hard-drive hanging issue can be resolved by using the SGIO library.
  26.  
  27. to compile, use: gcc -Wall -O -g -o SA-cover-poc SA-cover-poc.c
  28.  
  29. to read ID information from the drive, use: SA-cover-poc -p 0xport
  30. to write to reserved area, use: SA-cover-poc -p 0xport -w filename
  31. to read from reserved area, use: SA-cover-poc -p 0xport -r filename
  32.  
  33.  
  34. IMPORTANT: The code can render your data and hard-drive corrupted or otherwise inaccessible, use at your own risk!  
  35.  
  36. */
  37.  
  38.  
  39. #include <sys/io.h>
  40. #include <string.h>
  41. #include <stdio.h>
  42. #include <unistd.h>
  43. #include <stdlib.h>
  44. #include <ctype.h>
  45. #include <sys/types.h>
  46. #include <sys/stat.h>
  47.  
  48. #pragma pack(1)
  49.  
  50. #define ATA_SR_BSY     0x80
  51. #define ATA_SR_DRDY    0x40
  52. #define ATA_SR_DF      0x20
  53. #define ATA_SR_DSC     0x10
  54. #define ATA_SR_DRQ     0x08
  55. #define ATA_SR_CORR    0x04
  56. #define ATA_SR_IDX     0x02
  57. #define ATA_SR_ERR     0x01
  58.  
  59. // error consts
  60. #define ATA_ER_BBK      0x80
  61. #define ATA_ER_UNC      0x40
  62. #define ATA_ER_MC       0x20
  63. #define ATA_ER_IDNF     0x10
  64. #define ATA_ER_MCR      0x08
  65. #define ATA_ER_ABRT     0x04
  66. #define ATA_ER_TK0NF    0x02
  67. #define ATA_ER_AMNF     0x01
  68.  
  69. struct ide_id {
  70.         short general_conf;
  71.         short ob[9];
  72.         char sn[20];
  73.         short ob1[3];
  74.         char fwver[8];
  75.         char model[40];
  76.         short f1;
  77.         short res1;
  78.         short cap[2];
  79.         short ob2[9];
  80.         int lba28sec;
  81.         short ob3;
  82.         short mwdmamodes;
  83.         short piomodes;
  84.         short ob4[15];
  85.         short verma;
  86.         short vermi;
  87.         short features[6];
  88.         short dmamodes;
  89.         short secerasetime;
  90.         short ensecerasetime;
  91.         short apm;
  92.         short mpr;
  93.         short hwrs;
  94.         short ob5[6]; // +1
  95.         int lba48sec;
  96.         short ob6[13];
  97.         short wps;
  98.         short ob7[8];
  99.         short rms;
  100.         short secstat;
  101.         char vendorspec[62];
  102.         short cpapower;
  103.         char reserved_cf[30];
  104.         char media_sn[60];
  105.         char res[98];
  106.         short in;
  107. };
  108.  
  109.  
  110. struct zone_header {
  111.     short u1;
  112.     short zones;
  113.     char u2[0x10];
  114. } ;
  115.  
  116. struct zone_rec {
  117.     int start_cyl;
  118.     int end_cyl;
  119.     int start_sec;
  120.     char pad[2];
  121.     int end_sec;
  122.     char pad2[2];
  123. } ;
  124.  
  125. unsigned char regs;
  126. unsigned int busy, drdy, df, dsc, drq, corr, idx, err, ready, drsc;
  127. unsigned int bbk,unc,mc,idnf,mcr,abrt,tk0nf,amnf;
  128. unsigned short b0, b1,b2,b3,b4,b5,b6,b7;
  129. int p0,p1,p2,p3,p4,p5,p6,p7;
  130. int sa_spt, sa_tracks, num_of_heads, verbose;
  131.  
  132. void read_regs();
  133. void read_error();
  134. void status(int);
  135.  
  136. int waitready(int secs);
  137. int waitnobusy(int secs);
  138. int waitdrq(int secs);
  139. int waitnodrq(int secs);
  140.  
  141. int vsc_mode_on();
  142. int vsc_mode_off();
  143.  
  144. void write_buffer (char *sector);
  145. void read_buffer (char *sector);
  146.  
  147. int wd_dump_cp5 (char *buff);
  148.  
  149. int wd_rw_buffer_cmd(unsigned char length);
  150. int wd_send_full_cmd(short command, short p1, short p2, short p3, short p4, short p5, short p6);
  151. int wd_read_pchs(char *buffer, short head, int track, short sector, short scount);
  152. int wd_write_pchs(char *buffer, short head, int track, short sector, short scount);
  153. int wd_getcp(short cp, char **out_buff, int *len);
  154. int wd_send_cmd(short command, short para1 , short para2);
  155. int wd_id (struct ide_id *d);
  156. int write_file_to_reserved(char *filename);
  157. int read_file_from_reserved(char *filename);
  158. void flip (char *buf,int len);
  159. int get_sa_tracks(char *buf, int size);
  160. int get_sa_spt(char *buf);
  161.  
  162. int main(int argc, char **argv)
  163. {
  164.  
  165.     int c=0,portset=0;
  166.     int read_file=0, write_file=0,dump_zone_file=0;
  167.     int baseport=0;
  168.     char *bp=NULL;
  169.     char *filename=NULL;
  170.  
  171.     while ( (c = getopt(argc, argv, "hvzp:r:w:")) != -1 )
  172.     {
  173.  
  174.         switch (c)
  175.         {
  176.             case    'p':
  177.                 bp=optarg;
  178.                 portset=1;
  179.                 break;
  180.             case    'r':
  181.                 filename=optarg;
  182.                 read_file=1;
  183.                 break;
  184.             case    'w':
  185.                 filename=optarg;
  186.                 write_file=1;
  187.                 break;
  188.             case    'z':
  189.                 dump_zone_file=1;
  190.                 break;
  191.             case    'v':
  192.                 verbose=1;
  193.                 break;
  194.             case    'h':
  195.                 printf("usage: %s -p port [-r file] [-w filename] [-z] [-v]\n",argv[0]);
  196.                 printf("-r file     : read entire reserved area to file\n");
  197.                 printf("-w file     : write file onto reserved area\n");
  198.                 printf("-v      : verbose output\n");
  199.                 printf("-z      : dump zone file\n");
  200.                 printf("-h      : print this help\n");
  201.                 exit(1);
  202.                 break;
  203.         }
  204.        
  205.  
  206.     }
  207.  
  208.  
  209.     if (portset!=1)
  210.     {
  211.         printf("usage: %s -p port\ne.g. %s -p 0x0170\n",argv[0],argv[0]);
  212.         return(1);
  213.     }
  214.  
  215.         if (sscanf(bp, "0x%4x", &baseport))
  216.         {
  217.                 printf("using port address: 0x%04X\n\n", baseport);
  218.         } else {
  219.             if (sscanf(bp, "%4x", &baseport))
  220.                     printf("using port address: 0x%04X\n", baseport);
  221.         else
  222.         {
  223.             printf("unable to parse port argument (%s), aborting\n\n",bp);
  224.             return(1);
  225.         }
  226.         }
  227.  
  228.  
  229.  
  230.     // check for permissions
  231.     if (0!=iopl(3))
  232.     {
  233.         printf("can't change io privilege level, aborting\n");
  234.         return(1);
  235.     }
  236.  
  237.     p0=baseport;   
  238.  
  239.     p1=p0+1;
  240.     p2=p1+1;
  241.     p3=p2+1;
  242.     p4=p3+1;
  243.     p5=p4+1;
  244.     p6=p5+1;
  245.     p7=p6+1;
  246.  
  247.  
  248.     // also check if the drive model is what this POC is for...
  249.     char *poc_for_model="WDC WD2500KS-00MJB0";
  250.  
  251.     // disable interrupts?
  252.    
  253.     struct ide_id d;
  254.     wd_id(&d);
  255.  
  256.     if (verbose)
  257.         status(3);
  258.  
  259.     char model[64];
  260.     memset(model,0,64);
  261.     memcpy(model,d.model,40);
  262.     flip(model,40);
  263.     printf("Model: %s\n",model);
  264.  
  265.     char temp[64]={0};
  266.     memcpy(temp,d.sn,20);
  267.     flip(temp,20);
  268.     printf("S/N: %s\n",temp);
  269.  
  270.     memset(temp,0,64);
  271.     memcpy(temp,d.fwver,8);
  272.     flip(temp,8);
  273.     printf("F/W Ver:\t\t%s\n",temp);
  274.     printf ("LBA24:%d\tLBA48:%d\n",d.lba28sec, d.lba48sec);
  275.  
  276.     // checking for a specific 250GB hawk, but any other 250GB hawk would work just fine.
  277.     if (0!=strncmp (poc_for_model, model, strlen(poc_for_model)))
  278.     {
  279.         printf("POC works only on %s, the drive on port (%04X) is (%s), aborting\n",poc_for_model,p0,model);
  280.         exit(1);
  281.     }
  282.  
  283.  
  284.     char *out_buff;
  285.     int len;
  286.     // read configuration page 0x05 (zone list)
  287.     if (0==wd_getcp(0x05, &out_buff,&len))
  288.     {
  289.         sa_spt=get_sa_spt(out_buff);
  290.         sa_tracks=get_sa_tracks(out_buff,len*512);
  291.         num_of_heads=6; // constant for now.
  292.  
  293.         printf("\n\nService area sectors-per-track (%d)\nService area tracks (%d)\nNum of heads(%d)\nUnused reversed space (%d sectors [%d bytes])\n",sa_spt,sa_tracks,num_of_heads, sa_tracks*sa_spt*(num_of_heads - 2), sa_tracks*sa_spt*(num_of_heads - 2) * 512);
  294.     }
  295.  
  296.  
  297.     if (dump_zone_file)
  298.     {
  299.         wd_dump_cp5(out_buff);
  300.     }
  301.  
  302.     if (read_file)
  303.     {
  304.         printf("reading from SA to (%s) returned (%d)",filename,read_file_from_reserved(filename));
  305.     } else if (write_file) {
  306.         printf("writing to SA (%s) returned (%d)",filename,write_file_to_reserved(filename));
  307.     }
  308.  
  309.     return(vsc_mode_off());
  310. }
  311.  
  312. void write_buffer (char *sector)
  313. {
  314.     outsw(p0, sector, 256);
  315. }
  316.  
  317. void read_buffer (char *sector)
  318. {
  319.     insw(p0, sector, 256);
  320. }
  321.  
  322. void status(int times)
  323. {
  324.     int i=0;
  325.     printf("byte\tBSY\tDRDY\tDF\tDSC\tDRQ\tCORR\tIDX\tERR\tBBK\tUNC\tMC\tIDNF\tMCR\tABRT\tTK0NF\tAMNF\n");
  326.  
  327.     for (i=0;i<times;i++)
  328.     {
  329.         read_regs();
  330.         read_error();
  331.         printf("(%x)\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",regs,busy,drdy,df,dsc,drq,corr,idx,err,bbk,unc,mc,idnf,mcr,abrt,tk0nf,amnf);
  332.         usleep(200000);
  333.     }
  334. }
  335.  
  336. void read_regs()
  337. {
  338.  
  339.     unsigned char s ;
  340.     s = inb(p7);
  341.  
  342.     regs=s;
  343.    
  344.     busy = ATA_SR_BSY == (s & ATA_SR_BSY);
  345.     drdy = ATA_SR_DRDY == (s & ATA_SR_DRDY);        //drive ready
  346.     df = ATA_SR_DF == (s & ATA_SR_DF);
  347.     dsc = ATA_SR_DSC == (s & ATA_SR_DSC);           // drive seek complete
  348.     drq = ATA_SR_DRQ == (s & ATA_SR_DRQ);
  349.     corr = ATA_SR_CORR == (s & ATA_SR_CORR);
  350.     idx = ATA_SR_IDX == (s & ATA_SR_IDX);
  351.     err = ATA_SR_ERR == (s & ATA_SR_ERR);
  352.  
  353.     ready = drsc = drdy & dsc;
  354.    
  355. }  
  356.  
  357. void read_error()
  358. {
  359.     unsigned char e;
  360.     e = inb(p1);
  361.     bbk = ATA_ER_BBK == (e & ATA_ER_BBK);
  362.     unc = ATA_ER_UNC == (e & ATA_ER_UNC);
  363.     mc = ATA_ER_MC == (e & ATA_ER_MC);
  364.     idnf = ATA_ER_IDNF == (e & ATA_ER_IDNF);
  365.     mcr = ATA_ER_MCR == (e & ATA_ER_MCR);
  366.     abrt = ATA_ER_ABRT == (e & ATA_ER_ABRT);
  367.     tk0nf = ATA_ER_TK0NF == (e & ATA_ER_TK0NF);
  368.     amnf = ATA_ER_AMNF == (e & ATA_ER_AMNF);
  369.  
  370. }  
  371.  
  372. int wd_id (struct ide_id *d)
  373. {
  374.     if (verbose)
  375.         printf ("wd_id()\n");
  376.  
  377.     // send 0xa0 to p6  --select master
  378.     outb(0xa0, p6);
  379.  
  380.     // send 0xec to p7  --send identify cmd
  381.     outb(0xec, p7);
  382.  
  383.     if (waitdrq(10))
  384.     {
  385.         printf("not ready to read, aborting\n");
  386.     }
  387.  
  388.     // read buffer
  389.     char buff[512];
  390.     read_buffer (buff);
  391.  
  392.     memcpy(d,buff,sizeof(struct ide_id));
  393.  
  394.     return(0); 
  395. }
  396.  
  397. int wd_read_pchs ( char *buffer, short head, int track, short sector, short scount)
  398. {
  399.  
  400.     int sectorsread;
  401.     long int sectorslow;
  402.     long int sectorshigh;
  403.     char a[512];
  404.     int len;
  405.     int rc;
  406.  
  407.     // send 0xa0 to p6  --select master
  408.     outb(0xa0, p6);
  409.  
  410.     if (verbose)
  411.         printf("wd_read_pchs(head=%d)(track=%d)(sector=%d)(scount=%d)\n",head,track,sector,scount);
  412.  
  413.     if (waitready(3))
  414.     {
  415.         printf("wd_read_pchs: drive not ready, aborting\n");
  416.         status(3);
  417.         return(1);
  418.     }
  419.    
  420.     if (vsc_mode_on())
  421.     {  
  422.         printf("failed to get into vsc mode, aborting\n");
  423.         return (1);
  424.     }
  425.  
  426.     rc=wd_send_full_cmd(0x000c, 0x0001, (track & 0xffff), (track >> 16) & 0xffff , head, sector, scount);
  427.     if (rc)
  428.     {
  429.         printf("wd_read_pchs: wd_send_full_cmd failed, aborting\n");
  430.         return(1);
  431.     }
  432.  
  433.     if (waitnodrq(3)) {
  434.         printf("DRQ=1, ERROR\n");
  435.         return(1);
  436.     } else {
  437.         if (verbose)
  438.         {
  439.             printf("DRQ=0, OK\n");
  440.             status(4);
  441.         }
  442.     }
  443.  
  444.     sectorslow = inb(p4);
  445.     sectorshigh = inb(p5);
  446.     len = sectorslow+(sectorshigh<<8);
  447.  
  448.     if (len<1)
  449.     {
  450.         printf("len<1, aborting\n");
  451.         return(1);
  452.     }
  453.  
  454.     sectorsread=0;
  455.  
  456.     while (len>sectorsread)
  457.     {
  458.         rc=wd_rw_buffer_cmd(1);
  459.        if (rc)
  460.         {
  461.             printf("wd_rw_buffer_cmd, failed\n");
  462.             return(1);
  463.         }
  464.  
  465.         read_regs();
  466.         while (drq)
  467.         {
  468.             memset(a,0,512);
  469.             read_buffer(a);
  470.  
  471.             memcpy(buffer+(sectorsread*512), a, 512);
  472.  
  473.             sectorsread++;
  474.  
  475.             rc=waitready(60);
  476.             if (rc) return(1);
  477.  
  478.             read_regs();
  479.             if(err)
  480.             {
  481.                 printf("Error:\n");
  482.                 status(1);
  483.                 return(1); 
  484.             }
  485.         }
  486.     }
  487.  
  488.     if (sectorsread!=len)
  489.     {
  490.         printf("didn't complete read operation\n");
  491.         return(1);
  492.     }
  493.  
  494.     return(0);
  495. }
  496.  
  497. int vsc_mode_on()
  498. {
  499.  
  500.     int rc;
  501.  
  502.     // send 0xa0 to p6  --select master
  503.     outb(0xa0, p6);
  504.  
  505.     if (verbose)
  506.         printf("vsc_mode_on_start:\n");
  507.  
  508.     rc = waitnobusy(3);
  509.     if (rc)
  510.     {
  511.         printf("vsc_mode_on: busy, exiting\n");
  512.         status(3);
  513.         return(1);
  514.     }
  515.  
  516.     outb(0x45,p1);
  517.     outb(0x00,p2);
  518.     outb(0x00,p3);
  519.     outb(0x44,p4);
  520.     outb(0x57,p5);
  521.     outb(0xA0,p6);
  522.     outb(0x80,p7);
  523.  
  524.     rc=waitnobusy(10);
  525.     if (rc)
  526.     {
  527.         printf("wait-no-busy, timed out, aborting\n");
  528.         return(1);
  529.     }
  530.  
  531.     if(waitnodrq(3))
  532.     {
  533.         printf("drq still 1, aborting\n");
  534.         status(3);
  535.         return(1);
  536.     }
  537.    
  538.     if (verbose)
  539.         printf ("vsc_mode_on: OK\n");
  540.  
  541.     return(0);
  542.    
  543. }
  544.  
  545. int vsc_mode_off()
  546. {
  547.  
  548.     int rc;
  549.  
  550.     // send 0xa0 to p6  --select master
  551.     outb(0xa0, p6);
  552.  
  553.     if (verbose)
  554.         printf("vsc_mode_on_start:\n");
  555.  
  556.     rc = waitnobusy(3);
  557.     if (rc)
  558.     {
  559.         printf("vsc_mode_on: busy, exiting\n");
  560.         status(3);
  561.         return(1);
  562.     }
  563.  
  564.     outb(0x44,p1);
  565.     outb(0x00,p2);
  566.     outb(0x00,p3);
  567.     outb(0x44,p4);
  568.     outb(0x57,p5);
  569.     outb(0xA0,p6);
  570.     outb(0x80,p7);
  571.  
  572.     rc=waitnobusy(10);
  573.     if (rc)
  574.     {
  575.         printf("wait-no-busy, timed out, aborting\n");
  576.         return(1);
  577.     }
  578.  
  579.     read_regs();
  580.     if(drq)
  581.     {
  582.         printf("drq still 1, aborting\n");
  583.         status(3);
  584.         return(1);
  585.     }
  586.     return(0);
  587. }
  588.  
  589. int wd_rw_buffer_cmd(unsigned char length) 
  590. {
  591.  
  592.     int rc;
  593.  
  594.     // send 0xa0 to p6  --select master
  595.     outb(0xa0, p6);
  596.  
  597.     rc=waitnobusy(3);
  598.     if (rc)
  599.     {  
  600.         printf ("drive busy, aborting\n");
  601.         status(3);
  602.         return 1;
  603.     }
  604.  
  605.     outb(0xD5,p1);
  606.     outb(length,p2);
  607.     outb(0xbf,p3);
  608.     outb(0x4f,p4);
  609.     outb(0xc2,p5);
  610.     outb(0xa0,p6);
  611.     outb(0xb0,p7);
  612.  
  613.     rc=waitnobusy(60);
  614.     if (rc) {
  615.         printf ("io-wait-on-busy timeout,aborting\n");
  616.         status(2);
  617.         return(1);
  618.     }
  619.  
  620.     if (0!=waitdrq(3)) {
  621.         printf ("drq not on, aborting\n");
  622.         status(2);
  623.         return(1);
  624.     }
  625.  
  626.     if (verbose)
  627.         printf("wd_rw_buffer_cmd: OK\n");
  628.  
  629.     return(0);
  630. }
  631.  
  632.  
  633. int wd_send_full_cmd(short command, short par1, short par2, short par3, short par4, short par5, short par6)
  634. {
  635.     char a[512];
  636.     int rc;
  637.  
  638.     memset(a,0, 512);
  639.  
  640.     a[1]=(command>>8) & 0xff ;
  641.     a[0]=(command & 0x00ff);
  642.  
  643.     a[3]=(par1>>8) & 0xff;
  644.     a[2]=(par1 & 0x00ff);
  645.  
  646.     a[5]=(par2>>8) & 0xff;
  647.     a[4]=(par2 & 0x00ff);
  648.  
  649.     a[7]=(par3>>8) & 0xff;
  650.     a[6]=(par3 & 0x00ff);
  651.  
  652.     a[9]=(par4>>8) & 0xff;
  653.     a[8]=(par4 & 0x00ff);
  654.  
  655.     a[11]=(par5>>8) & 0xff;
  656.     a[10]=(par5 & 0x00ff);
  657.  
  658.     a[13]=(par6>>8) & 0xff;
  659.     a[12]=(par6 & 0x00ff);
  660.  
  661.  
  662.     outb(0xa0,p6);
  663.     read_regs();
  664.  
  665.     if (busy)
  666.     {
  667.         printf("wd_send_full_cmd: busy, exiting\n");
  668.         return 1;
  669.     }
  670.  
  671.     outb(0xd6,p1); 
  672.     outb(0x01,p2);
  673.     outb(0xbe,p3);
  674.     outb(0x4f,p4);
  675.     outb(0xc2,p5);
  676.     outb(0xa0,p6);
  677.     outb(0xb0,p7);
  678.  
  679.     rc=waitnobusy(60);
  680.     if(rc)
  681.     {
  682.  
  683.         printf("wd_send_full_cmd: waitnobusy (1), exiting\n");
  684.         return(1);
  685.     }
  686.  
  687.     read_regs();
  688.     if(!drq) {
  689.         printf ("wd_send_full_cmd: drq(%d), exiting\n",drq);
  690.         return(1);
  691.     }
  692.  
  693.     write_buffer(a);
  694.  
  695.     rc=waitnobusy(5);
  696.     if (rc) {
  697.         printf("wd_send_full_cmd: waitnobusy=%d, exiting\n,",rc);
  698.         return(1);
  699.     }
  700.  
  701.     read_regs();
  702.     if (err)
  703.     {
  704.            
  705.         printf("wd_send_full_cmd: error register is on..\n");
  706.         status(2);
  707.        
  708.         return(1);
  709.     }
  710.  
  711.     return(0);
  712. }
  713.  
  714. int waitdrq(int secs)
  715. {
  716.  
  717.     int wait_time=500;
  718.     int retries=secs*1000000/(wait_time);
  719.  
  720.     read_regs();
  721.     while ((!drq) && (retries>=0))
  722.     {
  723.         usleep (wait_time);
  724.         retries--;
  725.         read_regs();
  726.     }  
  727.  
  728.     if (retries>0)
  729.         return (0);
  730.     else
  731.         return(1);
  732.    
  733. }
  734.  
  735. int waitnodrq(int secs)
  736. {
  737.  
  738.     int wait_time=500;
  739.     int retries=secs*1000000/(wait_time);
  740.  
  741.     read_regs();
  742.     while ((drq) && (retries>=0))
  743.     {
  744.         usleep (wait_time);
  745.         retries--;
  746.         read_regs();
  747.     }  
  748.  
  749.     if (retries>0)
  750.         return (0);
  751.     else
  752.         return(1);
  753.    
  754. }
  755.  
  756. int waitready(int secs)
  757. {
  758.    
  759.     int wait_time=500;
  760.     int retries=secs*1000000/(wait_time);
  761.  
  762.     read_regs();
  763.     while ( (!ready) && (retries>=0))
  764.     {
  765.         usleep (wait_time);
  766.         retries--;
  767.         read_regs();
  768.     }  
  769.    
  770.     if (retries>0)
  771.         return (0);
  772.     else
  773.         return(1);
  774.    
  775. }
  776.  
  777. int waitnobusy(int secs)
  778. {
  779.  
  780.     int wait_time=500;
  781.     int retries=secs*1000000/(wait_time);
  782.  
  783.     read_regs();
  784.     while ((busy) && (retries>=0))
  785.     {
  786.         usleep (wait_time);
  787.         retries--;
  788.         read_regs();
  789.     }  
  790.    
  791.     if ((retries==0) && busy)
  792.         return (1);
  793.     else
  794.         return(0);
  795.    
  796. }
  797.  
  798.  
  799. int wd_send_cmd(short command, short par1 , short par2)
  800. {
  801.  
  802.     char a[512];
  803.     int rc;
  804.  
  805.     if (verbose)
  806.         printf("debug: (command=%04X)(p1=%04X)(p2=%04X)\n",command,par1,par2);
  807.  
  808.     memset(a,0, 512);
  809.  
  810.     a[1]=(command>>8) & 0xff ;
  811.     a[0]=(command & 0x00ff);
  812.  
  813.     a[3]=(par1>>8) & 0xff;
  814.     a[2]=(par1 & 0x00ff);
  815.  
  816.     a[5]=(par2>>8) & 0xff;
  817.     a[4]=(par2 & 0x00ff);
  818.  
  819.     // select master
  820.     outb(0xa0,p6);
  821.  
  822.     rc = waitnobusy(3);
  823.     if (rc)
  824.     {
  825.         printf("wd_send_full_cmd: drive busy, exiting\n");
  826.         return 1;
  827.     }
  828.  
  829.     outb(0xd6,p1);
  830.     outb(0x01,p2);
  831.     outb(0xbe,p3);
  832.     outb(0x4f,p4);
  833.     outb(0xc2,p5);
  834.     outb(0xa0,p6);
  835.     outb(0xb0,p7);
  836.  
  837.     rc=waitnobusy(3);
  838.     if(rc)
  839.     {
  840.  
  841.         printf("wd_send_full_cmd: waitnobusy (1), exiting\n");
  842.         return(1);
  843.     }
  844.  
  845.     read_regs();
  846.     if(!drq) {
  847.         printf ("wd_send_full_cmd: drq(%d), exiting\n",drq);
  848.         return(1);
  849.     }
  850.  
  851.     write_buffer(a);
  852.  
  853.     rc=waitnobusy(10);
  854.     if (rc) {
  855.         printf("wd_send_full_cmd: waitnobusy=%d, exiting\n,",rc);
  856.         return(1);
  857.     }
  858.  
  859.     read_regs();
  860.     if (err)
  861.     {
  862.            
  863.         printf("wd_send_full_cmd: error register is on..\n");
  864.         status(2);
  865.        
  866.         return(1);
  867.     }
  868.  
  869.     return(0);
  870. }
  871.  
  872.  
  873. int wd_getcp(short cp, char **out_buff, int *len)
  874. {
  875.  
  876.     char buff[512];
  877.     char *new_buff;
  878.     unsigned char i;
  879.     int rc = 0;
  880.  
  881.     // choose primary port
  882.     outb(0xa0,p6);
  883.  
  884.     read_regs();
  885.     if (busy)
  886.     {
  887.         printf("wd_getcp: drive busy, leaving");
  888.         return(1); 
  889.     }
  890.    
  891.     if (vsc_mode_on())
  892.     {
  893.         printf("wd_getcp: vsc_mode_on failed, aborting\n");
  894.         return(1);
  895.     }
  896.  
  897.     rc = wd_send_cmd(0x000d, cp, 0x0000);
  898.     if (rc)
  899.     {
  900.         printf("wd_getcp: wd_send_cmd failed, aborting\n");
  901.         status(2);
  902.         return(1);
  903.     }
  904.  
  905.     read_regs();
  906.     if (drq)
  907.     {
  908.         printf("wd_getcp: drq on, error, aborting\n");
  909.         status(2);
  910.         return(1);
  911.     }  
  912.  
  913.  
  914.     // read len
  915.     (*len) = inb(p4);
  916.  
  917.     new_buff=malloc((*len)*512);
  918.  
  919.     if (verbose)
  920.         printf("wd_getcp: CP (%x) len is (%x)\n", cp, *len);
  921.  
  922.     rc = wd_rw_buffer_cmd((*len));
  923.     if (rc)
  924.     {
  925.         printf("wd_getcp: wd_rw_buffer_cmd failed, aborting\n");
  926.         return(1);
  927.     }
  928.  
  929.     for (i=0;i<(*len);i++)
  930.     {
  931.         if (verbose)
  932.             printf("reading part (%d) of (%d)\n", i,(*len));
  933.  
  934.         if (0==waitdrq(3))
  935.         {
  936.             read_buffer(buff);
  937.             memcpy(new_buff+(i*512), buff,512);
  938.             waitnobusy(3);
  939.         }
  940.     }
  941.  
  942. #ifdef DEBUG
  943.     FILE *f;
  944.     char fn[64];
  945.     sprintf(fn, "cp_%x.bin",cp);
  946.     f = fopen(fn, "w");
  947.     if (f) {
  948.         fwrite(new_buff, 512*(*len),1, f);
  949.        fclose(f);
  950.     } else {
  951.         printf ("can't open file for writing... exiting\n");
  952.         return(1);
  953.     }
  954. #endif
  955.     (*out_buff)=new_buff;
  956.     return(0);
  957. }
  958.  
  959. int get_sa_spt(char *buff)
  960. {
  961.  
  962.     int pos=0;
  963.     short spt;
  964.  
  965.     pos+=sizeof(struct zone_header);
  966.     pos+=sizeof(struct zone_rec);
  967.  
  968.     memcpy(&spt,buff+pos, 2);
  969.  
  970.     return(spt);
  971. }
  972.  
  973.  
  974. int get_sa_tracks(char *buff, int size)
  975. {
  976.     struct zone_rec rec1;
  977.  
  978.     if ( (sizeof(struct zone_header) + sizeof(struct zone_rec)) < size )
  979.     {
  980.         memcpy(&rec1, buff + sizeof(struct zone_header), sizeof(struct zone_rec));
  981.         return(abs(rec1.start_cyl));
  982.     } else {
  983.         return(0);
  984.     }
  985. }
  986.  
  987.  
  988.  
  989. int wd_dump_cp5 (char *buff)
  990. {
  991.  
  992.     int i=0;
  993.     int h=0;
  994.     int num_of_heads=6;
  995.  
  996.     struct zone_rec rec1;
  997.     struct zone_header z1;
  998.  
  999.     memcpy(&z1, buff, sizeof(struct zone_header));
  1000.  
  1001.     int pos=0;
  1002.     short spt;
  1003.     pos+=sizeof(struct zone_header);   
  1004.     for (i=0;i<z1.zones;i++)   
  1005.     {
  1006.         memcpy(&rec1, buff+pos, sizeof(struct zone_rec));
  1007.         printf("cyl(%d,%d) sector(%d,%d)",rec1.start_cyl,rec1.end_cyl,rec1.start_sec,rec1.end_sec);
  1008.  
  1009.  
  1010.         pos+=sizeof(struct zone_rec);
  1011.  
  1012.         for(h=0;h<num_of_heads;h++)
  1013.         {
  1014.             memcpy(&spt,buff+pos, 2);
  1015.             pos+=2;
  1016.             printf (" (h=%d)(spt=%d)",h,spt);
  1017.         }
  1018.         printf("\n");
  1019.     }
  1020.  
  1021.     return(0);
  1022. }
  1023.  
  1024. int wd_write_pchs ( char *buffer, short head, int track, short sector, short scount)
  1025. {
  1026.     int sectorswritten;
  1027.     long int sectorslow;
  1028.     long int sectorshigh;
  1029.     char a[512];
  1030.     int len;
  1031.     int rc;
  1032.  
  1033.     if (verbose)
  1034.         printf("wd_write_pchs(head=%d)(track=%d)(sector=%d)(scount=%d)\n",head,track,sector,scount);
  1035.  
  1036.     outb(0xa0, p6);
  1037.  
  1038.     if (waitready(3))
  1039.     {
  1040.         printf("wd_write_pchs, drive not ready, aborting\n");
  1041.         status(3);
  1042.         return(1);
  1043.     }
  1044.    
  1045.     if (vsc_mode_on())
  1046.     {  
  1047.         printf("failed to get into vsc mode, aborting\n");
  1048.         return (1);
  1049.     } else {
  1050.         if (verbose)
  1051.             printf("vsc_mode_on: OK\n");
  1052.     }
  1053.  
  1054.  
  1055.     if (verbose)
  1056.         printf("debug: track(%04X)(%02X)(%02X)\n",track, (track & 0xffff), (track >> 16) & 0xffff);
  1057.  
  1058.     rc=wd_send_full_cmd(0x000c, 0x0002, (track & 0xffff), (track >> 16) & 0xffff , head, sector, scount);
  1059.     if (rc!=0)
  1060.     {
  1061.         printf("wd_send_full_cmd failed, aborting\n");
  1062.         return(1);
  1063.     } else {
  1064.         if (verbose)
  1065.             printf("wd_send_full_cmd: OK\n");
  1066.     }
  1067.  
  1068.     read_regs();
  1069.     if (drq) {
  1070.         printf("DRQ=1, ERROR\n");
  1071.         return(1);
  1072.     } else {
  1073.         if (verbose)
  1074.         {
  1075.             printf("DRQ=0, OK\n");
  1076.             status(2);
  1077.         }
  1078.     }
  1079.  
  1080.     sectorslow = inb(p4);
  1081.     sectorshigh = inb(p5);
  1082.     len = sectorslow+(sectorshigh<<8);
  1083.  
  1084.     if (len<1) return(1);
  1085.  
  1086.     sectorswritten=0;
  1087.  
  1088.     while (len>sectorswritten)
  1089.     {
  1090.             if (wd_rw_buffer_cmd(1))
  1091.         {
  1092.             printf("wd_rw_buffer_cmd, failed\n");
  1093.             return(1);
  1094.         }
  1095.  
  1096.         read_regs();
  1097.         while (drq)
  1098.         {
  1099.             if (memcpy(a,buffer+(sectorswritten*512),512))
  1100.             {
  1101.                 write_buffer(a);
  1102.             } else {
  1103.                 printf("error reading input buffer\n");
  1104.                 return(1);
  1105.             }
  1106.             sectorswritten++;
  1107.  
  1108.             rc=waitready(10);
  1109.             if (rc < 0)
  1110.             {  
  1111.                 printf("not ready aborting\n");
  1112.                 return(1);
  1113.             }
  1114.             read_regs();
  1115.             if(err)
  1116.             {
  1117.                 printf("write completed with errors, aborting\n");
  1118.                 return(1);
  1119.             }
  1120.         }
  1121.     }
  1122.  
  1123.     if (sectorswritten!=len)
  1124.     {  
  1125.         printf("didn't complete writing\n");
  1126.         return(1);
  1127.     }
  1128.  
  1129.     return(0);
  1130. }
  1131.  
  1132. void flip (char *buf,int len)
  1133. {
  1134.     int i=0;
  1135.     for (i=0;i<len-1;i+=2)
  1136.     {
  1137.         char k;
  1138.         k=buf[i];
  1139.         buf[i]=buf[i+1];
  1140.         buf[i+1]=k;
  1141.     }
  1142. }
  1143.  
  1144. int read_file_from_reserved(char *filename)
  1145. {
  1146.     // read from reserved areas 2,3,4,5
  1147.  
  1148.     char *whole_track;
  1149.     int h=0;
  1150.  
  1151.     if (sa_spt<=0)
  1152.     {
  1153.         printf("can't read sa_spt, aborting");
  1154.         return(1);
  1155.     }
  1156.  
  1157.     whole_track = malloc(sa_spt*512);
  1158.  
  1159.     FILE *f;
  1160.     f = fopen(filename, "w");
  1161.  
  1162.     h=2;    // first head with unused "service-area" space.
  1163.        
  1164.     int head,track;
  1165.     for (head=h;head<num_of_heads;head++)
  1166.     {
  1167.         for (track=-1;track>=(-1*sa_tracks);track--)
  1168.         {  
  1169.             printf("reading head(%d) track(%d)\n",head,track);
  1170.             if (0==wd_read_pchs(whole_track,head,track,1,sa_spt))
  1171.             {
  1172.                 fwrite(whole_track, sa_spt*512, 1, f);
  1173.             } else {
  1174.                 printf("wd_read_pchs failed, aborting\n");
  1175.                 return(1);
  1176.             }
  1177.         }
  1178.     }
  1179.  
  1180.     fclose(f);
  1181.     return(0);
  1182. }
  1183.  
  1184. int write_file_to_reserved(char *filename)
  1185. {
  1186.     // write to reserved areas 2,3,4,5
  1187.  
  1188.     char *whole_track;
  1189.     int size,rc=0;
  1190.  
  1191.     struct stat st;
  1192.     stat(filename, &st);
  1193.     size = st.st_size;
  1194.  
  1195.     if (sa_spt<=0)
  1196.     {
  1197.         printf("can't read sa_spt, aborting");
  1198.         return(1);
  1199.     }
  1200.  
  1201.     whole_track = malloc(sa_spt*512);
  1202.  
  1203.     if (size > (sa_spt * (sa_tracks) * 4 * 512))    // 4 is a fixed set of available heads for this drive.
  1204.     {
  1205.         printf("can't fit %s in SA, aborting (%d > %d)\n", filename, size, (sa_spt*(sa_tracks-1)*4*512));
  1206.         return(1);
  1207.     }
  1208.  
  1209.     FILE *f;
  1210.     f = fopen(filename, "r");
  1211.  
  1212.     int head=2;
  1213.     int track=-1;
  1214.     while ( (rc = fread(whole_track, 1, sa_spt*512, f)) )
  1215.     {
  1216.         // trim if not a complete sector.
  1217.         printf("writing head(%d) track(%d)\n",head,track);
  1218.         if (0==wd_write_pchs(whole_track, head, track, 1, (int)rc/512))
  1219.         {
  1220.             track--;
  1221.             if (track==-65)
  1222.             {
  1223.                 head++;
  1224.                 track=-1;
  1225.             }
  1226.         } else {
  1227.             printf("wd_write_pchs failed, aborting\n");
  1228.         }
  1229.     }
  1230.  
  1231.     printf("leaving write to file rc=%d\n",rc);
  1232.     return 0;
  1233. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement