]> Zhao Yanbai Git Server - minix.git/commitdiff
Added some more debug statements that are enablable by atapi_debug in the
authorBen Gras <ben@minix3.org>
Fri, 26 Aug 2005 19:39:00 +0000 (19:39 +0000)
committerBen Gras <ben@minix3.org>
Fri, 26 Aug 2005 19:39:00 +0000 (19:39 +0000)
boot monitor.

Added SCSI_SENSE command that asks the drive, with request sense, about
diagnostics for the previous error. This command is called and the results
printed when atapi_debug is enabled and atapi errors occur.

Debug output also prints actual commands sent to the drive.

Suddenly, Andy's problem has vanished. Don't know why, minor changes
(e.g. moving the atapi packet data from stack to static) shouldn't have
fixed this.. But with the debug info, we stand a better chance of
finding out what it was if it occurs again.

drivers/at_wini/at_wini.c

index 7e2f39989a03d8f85ec24e980dcd346e215f862a..c2f3842a0a4d50b00ccf56a81dbfe074bc86fcc5 100644 (file)
 #define   ATAPI_PACKETCMD       0xA0    /* packet command */
 #define   ATAPI_IDENTIFY        0xA1    /* identify drive */
 #define   SCSI_READ10           0x28    /* read from disk */
+#define   SCSI_SENSE            0x03    /* sense request */
 
 #define CD_SECTOR_SIZE         2048    /* sector size of a CD-ROM */
 #endif /* ATAPI */
 /* Interrupt request lines. */
 #define NO_IRQ          0      /* no IRQ set yet */
 
+#define ATAPI_PACKETSIZE       12
+#define SENSE_PACKETSIZE       18
+
 /* Common command block */
 struct command {
   u8_t precomp;        /* REG_PRECOMP, etc. */
@@ -178,7 +182,8 @@ struct command {
 /* Timeouts and max retries. */
 int timeout_ticks = DEF_TIMEOUT_TICKS, max_errors = MAX_ERRORS;
 int wakeup_ticks = WAKEUP;
-long w_standard_timeouts = 0, w_pci_debug = 0, w_instance = 0, w_lba48 = 0;
+long w_standard_timeouts = 0, w_pci_debug = 0, w_instance = 0,
+ w_lba48 = 0, atapi_debug = 0;
 
 int w_testing = 0, w_silent = 0;
 
@@ -307,6 +312,7 @@ PRIVATE void init_params()
   env_parse("ata_pci_debug", "d", 0, &w_pci_debug, 0, 1);
   env_parse("ata_instance", "d", 0, &w_instance, 0, 8);
   env_parse("ata_lba48", "d", 0, &w_lba48, 0, 1);
+  env_parse("atapi_debug", "d", 0, &atapi_debug, 0, 1);
 
   if(w_instance == 0) {
          /* Get the number of drives from the BIOS data area */
@@ -438,7 +444,7 @@ PRIVATE void init_params_pci(int skip)
                                base_cmd, base_ctl, irq, 1, irq_hook, 0);
                        init_drive(&wini[w_next_drive+1],
                                base_cmd, base_ctl, irq, 1, irq_hook, 1);
-                       if(w_pci_debug || 1)
+                       if(w_pci_debug)
                                printf("atapci %d: 0x%x 0x%x irq %d\n", devind, base_cmd, base_ctl, irq);
                } else printf("atapci: ignored drives on primary channel, base %x\n", base_cmd);
        }
@@ -453,7 +459,7 @@ PRIVATE void init_params_pci(int skip)
                                base_cmd, base_ctl, irq, 1, irq_hook, 2);
                        init_drive(&wini[w_next_drive+3],
                                base_cmd, base_ctl, irq, 1, irq_hook, 3);
-                       if(w_pci_debug || 1)
+                       if(w_pci_debug)
                                printf("atapci %d: 0x%x 0x%x irq %d\n", devind, base_cmd, base_ctl, irq);
                } else printf("atapci: ignored drives on secondary channel, base %x\n", base_cmd);
        }
@@ -544,7 +550,10 @@ message *m_ptr;
 PRIVATE struct device *w_prepare(int device)
 {
 /* Prepare for I/O on a device. */
+struct wini *prev_wn;
+prev_wn = w_wn;
   w_device = device;
+
   if (device < NR_MINORS) {                    /* d0, d0p[0-3], d1, ... */
        w_drive = device / DEV_PER_DRIVE;       /* save drive number */
        w_wn = &wini[w_drive];
@@ -671,15 +680,6 @@ PRIVATE int w_identify()
        return(ERR);
   }
 
-#if VERBOSE
-  printf("%s: user-space AT driver detected ", w_name());
-  if (wn->state & (SMART|ATAPI)) {
-       printf("%.40s\n", id_string);
-  } else {
-       printf("%ux%ux%u\n", wn->pcylinders, wn->pheads, wn->psectors);
-  }
-#endif
-
   if(wn->irq == NO_IRQ) {
          /* Everything looks OK; register IRQ so we can stop polling. */
          wn->irq = w_drive < 2 ? AT_WINI_0_IRQ : AT_WINI_1_IRQ;
@@ -1266,6 +1266,36 @@ PRIVATE void atapi_close()
 /* Should unlock the device.  For now do nothing.  (XXX) */
 }
 
+void sense_request(void)
+{
+       int r, i;
+       static u8_t sense[100], packet[ATAPI_PACKETSIZE];
+
+       packet[0] = SCSI_SENSE;
+       packet[1] = 0;
+       packet[2] = 0;
+       packet[3] = 0;
+       packet[4] = SENSE_PACKETSIZE;
+       packet[5] = 0;
+       packet[7] = 0;
+       packet[8] = 0;
+       packet[9] = 0;
+       packet[10] = 0;
+       packet[11] = 0;
+
+       for(i = 0; i < SENSE_PACKETSIZE; i++) sense[i] = 0xff;
+       r = atapi_sendpacket(packet, SENSE_PACKETSIZE);
+       if (r != OK) { printf("request sense command failed\n"); return; }
+       if(atapi_intr_wait() <= 0) { printf("WARNING: request response failed\n"); }
+
+       if (sys_insw(w_wn->base_cmd + REG_DATA, SELF, (void *) sense, SENSE_PACKETSIZE) != OK)
+               printf("WARNING: sense reading failed\n");
+
+       printf("sense data:");
+       for(i = 0; i < SENSE_PACKETSIZE; i++) printf(" %02x", sense[i]);
+       printf("\n");
+}
+
 /*===========================================================================*
  *                             atapi_transfer                               *
  *===========================================================================*/
@@ -1283,7 +1313,7 @@ unsigned nr_req;          /* length of request vector */
   unsigned long block;
   unsigned long dv_size = cv64ul(w_dv->dv_size);
   unsigned nbytes, nblocks, count, before, chunk;
-  u8_t packet[12];
+  static u8_t packet[ATAPI_PACKETSIZE];
 
   errors = fresh = 0;
 
@@ -1386,10 +1416,13 @@ unsigned nr_req;                /* length of request vector */
 
        if (r < 0) {
   err:         /* Don't retry if too many errors. */
+               if(atapi_debug) sense_request();
                if (++errors == max_errors) {
                        w_command = CMD_IDLE;
+                       if(atapi_debug) printf("giving up (%d)\n", errors);
                        return(EIO);
                }
+               if(atapi_debug) printf("retry (%d)\n", errors);
        }
   }
 
@@ -1439,6 +1472,7 @@ unsigned cnt;
   pv_set(outbyte[3], wn->base_cmd + REG_CNT_LO, (cnt >> 0) & 0xFF);
   pv_set(outbyte[4], wn->base_cmd + REG_CNT_HI, (cnt >> 8) & 0xFF);
   pv_set(outbyte[5], wn->base_cmd + REG_COMMAND, w_command);
+  if(atapi_debug) printf("cmd: %x  ", w_command);
   if ((s=sys_voutb(outbyte,6)) != OK)
        panic(w_name(),"Couldn't write registers with sys_voutb()",s);
 
@@ -1449,8 +1483,17 @@ unsigned cnt;
   wn->w_status |= STATUS_ADMBSY;               /* Command not at all done yet. */
 
   /* Send the command packet to the device. */
-  if ((s=sys_outsw(wn->base_cmd + REG_DATA, SELF, packet, 12)) != OK)
+  if ((s=sys_outsw(wn->base_cmd + REG_DATA, SELF, packet, ATAPI_PACKETSIZE)) != OK)
        panic(w_name(),"sys_outsw() failed", s);
+
+ {
+ int p;
+ if(atapi_debug) {
+       printf("sent command:");
+        for(p = 0; p < ATAPI_PACKETSIZE; p++) { printf(" %02x", packet[p]); }
+        printf("\n");
+       }
+ }
   return(OK);
 }
 
@@ -1546,6 +1589,39 @@ PRIVATE void ack_irqs(unsigned int irqs)
   }
 }
 
+
+#define STSTR(a) if(status & STATUS_ ## a) { strcat(str, #a); strcat(str, " "); }
+#define ERRSTR(a) if(e & ERROR_ ## a) { strcat(str, #a); strcat(str, " "); }
+char *strstatus(int status)
+{
+       static char str[200];
+       str[0] = '\0';
+
+       STSTR(BSY);
+       STSTR(DRDY);
+       STSTR(DMADF);
+       STSTR(SRVCDSC);
+       STSTR(DRQ);
+       STSTR(CORR);
+       STSTR(CHECK);
+       return str;
+}
+
+char *strerr(int e)
+{
+       static char str[200];
+       str[0] = '\0';
+
+       ERRSTR(BB);
+       ERRSTR(ECC);
+       ERRSTR(ID);
+       ERRSTR(AC);
+       ERRSTR(TK);
+       ERRSTR(DM);
+
+       return str;
+}
+
 /*============================================================================*
  *                             atapi_intr_wait                               *
  *============================================================================*/
@@ -1577,10 +1653,15 @@ PRIVATE int atapi_intr_wait()
   len |= inbyte[2].value << 8;
   irr = inbyte[3].value;
 
-  if (ATAPI_DEBUG) {
-       printf("S=%02x E=%02x L=%04x I=%02x\n", wn->w_status, e, len, irr);
+#if ATAPI_DEBUG
+       printf("wn %p  S=%x=%s E=%02x=%s L=%04x I=%02x\n", wn, wn->w_status, strstatus(wn->w_status), e, strerr(e), len, irr);
+#endif
+  if (wn->w_status & (STATUS_BSY | STATUS_CHECK)) {
+       if(atapi_debug) {
+               printf("atapi fail:  S=%x=%s E=%02x=%s L=%04x I=%02x\n", wn->w_status, strstatus(wn->w_status), e, strerr(e), len, irr);
+       }
+       return ERR;
   }
-  if (wn->w_status & (STATUS_BSY | STATUS_CHECK)) return ERR;
 
   phase = (wn->w_status & STATUS_DRQ) | (irr & (IRR_COD | IRR_IO));