From d0cd846ae83465b7a1ad15bd3969b372121a6022 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Fri, 26 Aug 2005 19:39:00 +0000 Subject: [PATCH] Added some more debug statements that are enablable by atapi_debug in the 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 | 115 ++++++++++++++++++++++++++++++++------ 1 file changed, 98 insertions(+), 17 deletions(-) diff --git a/drivers/at_wini/at_wini.c b/drivers/at_wini/at_wini.c index 7e2f39989..c2f3842a0 100644 --- a/drivers/at_wini/at_wini.c +++ b/drivers/at_wini/at_wini.c @@ -122,6 +122,7 @@ #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 */ @@ -129,6 +130,9 @@ /* 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));