?? cmd_ide.c
字號:
ide_led (DEVICE_LED(device), 0); /* LED off */ return (n);}/* ------------------------------------------------------------------------- */ulong ide_write (int device, ulong blknr, ulong blkcnt, ulong *buffer){ ulong n = 0; unsigned char c; ide_led (DEVICE_LED(device), 1); /* LED on */ /* Select device */ outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); while (blkcnt-- > 0) { c = ide_wait (device, IDE_TIME_OUT); if (c & ATA_STAT_BUSY) { printf ("IDE read: device %d not ready\n", device); goto WR_OUT; } outb (device, ATA_SECT_CNT, 1); outb (device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); outb (device, ATA_LBA_MID, (blknr >> 8) & 0xFF); outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device) | ((blknr >> 24) & 0xF) ); outb (device, ATA_COMMAND, ATA_CMD_WRITE); udelay (50); c = ide_wait (device, IDE_TIME_OUT); /* can't take over 500 ms */ if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != ATA_STAT_DRQ) { printf ("Error (no IRQ) dev %d blk %ld: status 0x%02x\n", device, blknr, c); goto WR_OUT; } output_data (device, buffer, ATA_SECTORWORDS); c = inb (device, ATA_STATUS); /* clear IRQ */ ++n; ++blknr; buffer += ATA_SECTORWORDS; }WR_OUT: ide_led (DEVICE_LED(device), 0); /* LED off */ return (n);}/* ------------------------------------------------------------------------- *//* copy src to dest, skipping leading and trailing blanks and null terminate the string */static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len){ int start,end; start=0; while(start<len) { if(src[start]!=' ') break; start++; } end=len-2; /* we need to cut of the last character for the ending \0 !!! */ while(end>start) { if(src[end]!=' ') break; end--; } for( ; start<=end; start++) { *dest++=src[start]; } *dest='\0';}/* ------------------------------------------------------------------------- *//* * Wait until Busy bit is off, or timeout (in ms) * Return last status */static uchar ide_wait (int dev, ulong t){ ulong delay = 10 * t; /* poll every 100 us */ uchar c; while ((c = inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { udelay (100); if (delay-- == 0) { break; } } return (c);}/* ------------------------------------------------------------------------- */#ifdef CONFIG_IDE_RESET#ifdef CONFIG_IDE_RESET_ROUTINEextern void ide_set_reset(int idereset);#endifstatic void ide_reset (void){ int i;#if defined(CFG_PC_IDE_RESET) volatile immap_t *immr = (immap_t *)CFG_IMMR;#endif curr_device = -1; for (i=0; i<CFG_IDE_MAXBUS; ++i) ide_bus_ok[i] = 0; for (i=0; i<CFG_IDE_MAXDEVICE; ++i) ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;#if defined(CFG_PC_IDE_RESET) /* Configure PC for IDE Reset Pin */ immr->im_ioport.iop_pcdat &= ~(CFG_PC_IDE_RESET); /* Set reset bit */ immr->im_ioport.iop_pcpar &= ~(CFG_PC_IDE_RESET); immr->im_ioport.iop_pcso &= ~(CFG_PC_IDE_RESET); immr->im_ioport.iop_pcdir |= CFG_PC_IDE_RESET; /* Make output */ /* assert IDE RESET signal */ immr->im_ioport.iop_pcdat &= ~(CFG_PC_IDE_RESET); udelay (20000); /* de-assert RESET signal of IDE */ immr->im_ioport.iop_pcdat |= CFG_PC_IDE_RESET;#else#ifdef CONFIG_IDE_RESET_ROUTINE ide_set_reset(1); /* assert reset */ udelay (20000); /* de-assert RESET signal of IDE */ ide_set_reset(0); #else#error IDE reset pin not configured#endif /* CONFIG_IDE_RESET_ROUTINE */#endif /* CFG_PC_IDE_RESET */#if defined(CONFIG_WATCHDOG) watchdog_reset ();#endif /* CONFIG_WATCHDOG */#ifdef CFG_PB_12V_ENABLE /* We must wait at least 500 ms for the voltage to stabilize; */ for (i=0; i<50; ++i) { udelay (10000); }#if defined(CONFIG_WATCHDOG) watchdog_reset ();#endif /* CONFIG_WATCHDOG */ immr->im_cpm.cp_pbdat |= CFG_PB_12V_ENABLE; /* 12V Enable output ON */ immr->im_cpm.cp_pbpar &= ~(CFG_PB_12V_ENABLE); immr->im_cpm.cp_pbodr &= ~(CFG_PB_12V_ENABLE); immr->im_cpm.cp_pbdir |= CFG_PB_12V_ENABLE;#endif /* CFG_PB_12V_ENABLE */#ifdef CFG_PB_IDE_MOTOR immr->im_cpm.cp_pbpar &= ~(CFG_PB_IDE_MOTOR); /* IDE Motor in pin */ immr->im_cpm.cp_pbodr &= ~(CFG_PB_IDE_MOTOR); immr->im_cpm.cp_pbdir &= ~(CFG_PB_IDE_MOTOR); /* input */ if ((immr->im_cpm.cp_pbdat & CFG_PB_IDE_MOTOR) == 0) { printf ("\nWarning: 5V for IDE Motor missing\n");# ifdef CONFIG_STATUS_LED# ifdef STATUS_LED_YELLOW status_led_set (STATUS_LED_YELLOW, STATUS_LED_ON );# endif# ifdef STATUS_LED_GREEN status_led_set (STATUS_LED_GREEN, STATUS_LED_OFF);# endif# endif /* CONFIG_STATUS_LED */ }#endif /* CFG_PB_IDE_MOTOR */#if defined(CONFIG_WATCHDOG) watchdog_reset ();#endif /* CONFIG_WATCHDOG */ /* wait 250 ms */ for (i=0; i<25; ++i) { udelay (10000); }#if defined(CONFIG_WATCHDOG) watchdog_reset ();#endif /* CONFIG_WATCHDOG */}#endif /* CONFIG_IDE_RESET *//* ------------------------------------------------------------------------- */#ifdef CONFIG_IDE_LEDstatic uchar led_buffer = 0; /* Buffer for current LED status */static void ide_led (uchar led, uchar status){ uchar *led_port = LED_PORT; if (status) { /* switch LED on */ led_buffer |= led; } else { /* switch LED off */ led_buffer &= ~led; } *led_port = led_buffer;}#endif /* CONFIG_IDE_LED *//* ------------------------------------------------------------------------- */#ifdef CONFIG_ATAPI/**************************************************************************** * ATAPI Support */#undef ATAPI_DEBUG#ifdef ATAPI_DEBUG#define AT_PRINTF(fmt,args...) printf (fmt ,##args)#else#define AT_PRINTF(fmt,args...)#endif/* * issue an atapi command */unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned char * buffer,int buflen){ unsigned char c,err; int n; ide_led (DEVICE_LED(device), 1); /* LED on */ /* Select device */ outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); c = ide_wait (device, ATAPI_TIME_OUT); if (c & ATA_STAT_BUSY) { printf ("ATAPI_ISSUE: device %d not ready\n", device); err=0xff; goto AI_OUT; } outb (device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ outb (device, ATA_CYL_LOW, (unsigned char)(buflen & 0xff)); outb (device, ATA_CYL_HIGH, (unsigned char)((buflen<<8) & 0xff)); outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); outb (device, ATA_COMMAND, ATAPI_CMD_PACKET); udelay (50); c = ide_wait (device, ATAPI_TIME_OUT); /* can't take over 500 ms */ if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != ATA_STAT_DRQ) { /* DRQ must be 1, BSY 0 */ printf ("ATTAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n",device,c); err=0xff; goto AI_OUT; } output_data (device, (unsigned long *)ccb,ccblen/2); /* write command block */ /*while((inb(device,ATA_STATUS) & ATA_STAT_BUSY)==0) */ udelay (50); /* device must set bsy */ /*c = inb (device, ATA_STATUS);*/ /* clear IRQ */ c = ide_wait (device, ATAPI_TIME_OUT); /* wait until BSY=0, DRQ=1 */ if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != ATA_STAT_DRQ) { if((c&ATA_STAT_ERR) == ATA_STAT_ERR) { err=(inb(device,ATA_ERROR_REG)); AT_PRINTF("atapi_issue returned sense key %X\n",err); } else { /* maybe no data command ? */ if(buflen==0) err=0; else { printf ("ATTAPI_ISSUE: (no IRQ) after sending ccb (%x) status 0x%02x\n", ccb[0],c); err=0xff; } } goto AI_OUT; } n=inb(device, ATA_CYL_HIGH); n<<=8; n+=inb(device, ATA_CYL_LOW); AT_PRINTF("ATAPI_ISSUE: %d Bytes to transfer\n",n); /* ok now decide if it is an in or output */ if((inb(device, ATA_SECT_CNT)&0x02)==0) { AT_PRINTF("Write to device\n"); output_data(device,(unsigned long *)buffer,n>>2); } else { AT_PRINTF("Read from device @ %p words %d\n",buffer,n>>2); input_data(device,(unsigned long *)buffer,n>>2); } c = inb (device, ATA_STATUS); /* clear IRQ */ if((c & ATA_STAT_ERR) == ATA_STAT_ERR) { err=(inb(device,ATA_ERROR_REG) >> 8) &0x0f; AT_PRINTF("atapi_issue returned sense key %X\n",err); } else err = 0;AI_OUT: ide_led (DEVICE_LED(device), 0); /* LED off */ return(err);}/* * sending the command to atapi_issue. If an status other than good returns, an request_sense * will be issued */unsigned char atapi_issue_autoreq(int device,unsigned char* ccb,int ccblen, unsigned char * buffer,int buflen){ unsigned char sense_data[16],sense_ccb[12]; unsigned char res; int i,retrycnt; retrycnt=0;retry: res= atapi_issue(device,ccb,ccblen,buffer,buflen); if(res==0) return (0); /* Ok */ if(res==0xff) return (0xff); /* error */ AT_PRINTF("(auto_req)atapi_issue returned sense key %X\n",res); for(i=0;i<12;i++) sense_ccb[i]=0; /* initialize it to zero */ sense_ccb[0]=ATAPI_CMD_REQ_SENSE; sense_ccb[4]=16; /* allocation Legnth */ res=atapi_issue(device,sense_ccb,12,sense_data,14); AT_PRINTF("ATAPI_CMD_REQ_SENSE returned %x\n",res); AT_PRINTF(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n",sense_data[0],sense_data[2]&0xf,sense_data[12],sense_data[13]); if(((sense_data[2]&0xf)==0) && (sense_data[12]==0) && (sense_data[13]==0)) return(0); /* ok device ready */ if(((sense_data[2]&0xf)==0x02) && (sense_data[12]==0x04) && (sense_data[13]!=0x01)) { printf("Error\n"); return (0xff); } if(((sense_data[2]&0xf)==0x02) && (sense_data[12]==0x3A)) { AT_PRINTF("Media not present\n"); return (0xff); } if((sense_data[2]&0xf)==0x06) { AT_PRINTF("Unit attention...retry\n"); if(retrycnt++<4) goto retry; return (0xff); } printf("unknown sense_key\n"); return(0xff);}static void atapi_inquiry(block_dev_desc_t * dev_desc){ unsigned char ccb[12]; /* Command descriptor block */ unsigned char iobuf[64]; /* temp buf */ unsigned char c; int i,device; device=dev_desc->dev; dev_desc->type=DEV_TYPE_UNKNOWN; /* not yet valid */ dev_desc->block_read=atapi_read; for(i=0;i<12;i++) ccb[i]=0; /* initialize it to zero */ ccb[0]=ATAPI_CMD_INQUIRY; ccb[4]=40; /* allocation Legnth */ c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,40); AT_PRINTF("ATAPI_CMD_INQUIRY returned %x\n",c); if(c!=0) return; /* copy device ident strings */ ident_cpy(dev_desc->vendor,&iobuf[8],8); ident_cpy(dev_desc->product,&iobuf[16],16); ident_cpy(dev_desc->revision,&iobuf[32],5); dev_desc->lun=0; dev_desc->lba=0; dev_desc->blksz=0; dev_desc->type=iobuf[0] & 0x1f; if((iobuf[1]&0x80)==0x80) dev_desc->removable = 1; else dev_desc->removable = 0; for(i=0;i<12;i++) ccb[i]=0; /* initialize it to zero */ ccb[0]=ATAPI_CMD_START_STOP; ccb[4]=0x01; /* start */ c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,0); AT_PRINTF("ATAPI_CMD_START_STOP returned %x\n",c); if(c!=0) return; for(i=0;i<12;i++) ccb[i]=0; /* initialize it to zero */ ccb[0]=ATAPI_CMD_READ_CAP; c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,8); AT_PRINTF("ATAPI_CMD_READ_CAP returned %x\n",c); if(c!=0) return; AT_PRINTF("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n",iobuf[0],iobuf[1],iobuf[2],iobuf[3], iobuf[4],iobuf[5],iobuf[6],iobuf[7]); dev_desc->lba=((unsigned long)iobuf[0]<<24)+((unsigned long)iobuf[1]<<16)+((unsigned long)iobuf[2]<<8)+((unsigned long)iobuf[3]); dev_desc->blksz=((unsigned long)iobuf[4]<<24)+((unsigned long)iobuf[5]<<16)+((unsigned long)iobuf[6]<<8)+((unsigned long)iobuf[7]); return;}/* * atapi_read: * we transfer only one block per command, since the multiple DRQ per command is not yet implemented */#define ATAPI_READ_MAX_BYTES 2048 /* we read max 32kbytes */#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */#define ATAPI_READ_MAX_BLOCK ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE /* max blocks */ulong atapi_read (int device, ulong blknr, ulong blkcnt, ulong *buffer){ ulong n = 0; unsigned char ccb[12]; /* Command descriptor block */ ulong cnt; AT_PRINTF("atapi_read dev %d start %lX, blocks %lX buffer at %lX\n",device,blknr,blkcnt,(ulong)buffer); do { if(blkcnt>ATAPI_READ_MAX_BLOCK) { cnt=ATAPI_READ_MAX_BLOCK; } else { cnt=blkcnt; } ccb[0]=ATAPI_CMD_READ_12; ccb[1]=0; /* reserved */ ccb[2]=(unsigned char) (blknr>>24) & 0xff; /* MSB Block */ ccb[3]=(unsigned char) (blknr>>16) & 0xff; /* */ ccb[4]=(unsigned char) (blknr>>8) & 0xff; ccb[5]=(unsigned char) blknr & 0xff; /* LSB Block */ ccb[6]=(unsigned char) (cnt>>24) & 0xff; /* MSB Block count */ ccb[7]=(unsigned char) (cnt>>16) & 0xff; ccb[8]=(unsigned char) (cnt>>8) & 0xff; ccb[9]=(unsigned char) cnt & 0xff; /* LSB Block */ ccb[10]=0; /* reserved */ ccb[11]=0; /* reserved */ if(atapi_issue_autoreq(device,ccb,12,(unsigned char *)buffer,cnt*ATAPI_READ_BLOCK_SIZE)==0xff) return(n); n+=cnt; blkcnt-=cnt; blknr+=cnt; buffer+=cnt*(ATAPI_READ_BLOCK_SIZE/4); /* ulong blocksize in ulong */ } while(blkcnt>0); return(n);}/* ------------------------------------------------------------------------- */#endif /* CONFIG_ATAPI */#endif /* CONFIG_COMMANDS & CFG_CMD_IDE */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -