fdc.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2001
  4. * Denis Peter, MPL AG, d.peter@mpl.ch.
  5. */
  6. /*
  7. * Floppy Disk support
  8. */
  9. #include <common.h>
  10. #include <config.h>
  11. #include <command.h>
  12. #include <image.h>
  13. #undef FDC_DEBUG
  14. #ifdef FDC_DEBUG
  15. #define PRINTF(fmt,args...) printf (fmt ,##args)
  16. #else
  17. #define PRINTF(fmt,args...)
  18. #endif
  19. /*#if defined(CONFIG_CMD_DATE) */
  20. /*#include <rtc.h> */
  21. /*#endif */
  22. typedef struct {
  23. int flags; /* connected drives ect */
  24. unsigned long blnr; /* Logical block nr */
  25. uchar drive; /* drive no */
  26. uchar cmdlen; /* cmd length */
  27. uchar cmd[16]; /* cmd desc */
  28. uchar dma; /* if > 0 dma enabled */
  29. uchar result[11]; /* status information */
  30. uchar resultlen; /* lenght of result */
  31. } FDC_COMMAND_STRUCT;
  32. /* flags: only the lower 8bit used:
  33. * bit 0 if set drive 0 is present
  34. * bit 1 if set drive 1 is present
  35. * bit 2 if set drive 2 is present
  36. * bit 3 if set drive 3 is present
  37. * bit 4 if set disk in drive 0 is inserted
  38. * bit 5 if set disk in drive 1 is inserted
  39. * bit 6 if set disk in drive 2 is inserted
  40. * bit 7 if set disk in drive 4 is inserted
  41. */
  42. /* cmd indexes */
  43. #define COMMAND 0
  44. #define DRIVE 1
  45. #define CONFIG0 1
  46. #define SPEC_HUTSRT 1
  47. #define TRACK 2
  48. #define CONFIG1 2
  49. #define SPEC_HLT 2
  50. #define HEAD 3
  51. #define CONFIG2 3
  52. #define SECTOR 4
  53. #define SECTOR_SIZE 5
  54. #define LAST_TRACK 6
  55. #define GAP 7
  56. #define DTL 8
  57. /* result indexes */
  58. #define STATUS_0 0
  59. #define STATUS_PCN 1
  60. #define STATUS_1 1
  61. #define STATUS_2 2
  62. #define STATUS_TRACK 3
  63. #define STATUS_HEAD 4
  64. #define STATUS_SECT 5
  65. #define STATUS_SECT_SIZE 6
  66. /* Register addresses */
  67. #define FDC_BASE 0x3F0
  68. #define FDC_SRA FDC_BASE + 0 /* Status Register A */
  69. #define FDC_SRB FDC_BASE + 1 /* Status Register B */
  70. #define FDC_DOR FDC_BASE + 2 /* Digital Output Register */
  71. #define FDC_TDR FDC_BASE + 3 /* Tape Drive Register */
  72. #define FDC_DSR FDC_BASE + 4 /* Data rate Register */
  73. #define FDC_MSR FDC_BASE + 4 /* Main Status Register */
  74. #define FDC_FIFO FDC_BASE + 5 /* FIFO */
  75. #define FDC_DIR FDC_BASE + 6 /* Digital Input Register */
  76. #define FDC_CCR FDC_BASE + 7 /* Configuration Control */
  77. /* Commands */
  78. #define FDC_CMD_SENSE_INT 0x08
  79. #define FDC_CMD_CONFIGURE 0x13
  80. #define FDC_CMD_SPECIFY 0x03
  81. #define FDC_CMD_RECALIBRATE 0x07
  82. #define FDC_CMD_READ 0x06
  83. #define FDC_CMD_READ_TRACK 0x02
  84. #define FDC_CMD_READ_ID 0x0A
  85. #define FDC_CMD_DUMP_REG 0x0E
  86. #define FDC_CMD_SEEK 0x0F
  87. #define FDC_CMD_SENSE_INT_LEN 0x01
  88. #define FDC_CMD_CONFIGURE_LEN 0x04
  89. #define FDC_CMD_SPECIFY_LEN 0x03
  90. #define FDC_CMD_RECALIBRATE_LEN 0x02
  91. #define FDC_CMD_READ_LEN 0x09
  92. #define FDC_CMD_READ_TRACK_LEN 0x09
  93. #define FDC_CMD_READ_ID_LEN 0x02
  94. #define FDC_CMD_DUMP_REG_LEN 0x01
  95. #define FDC_CMD_SEEK_LEN 0x03
  96. #define FDC_FIFO_THR 0x0C
  97. #define FDC_FIFO_DIS 0x00
  98. #define FDC_IMPLIED_SEEK 0x01
  99. #define FDC_POLL_DIS 0x00
  100. #define FDC_PRE_TRK 0x00
  101. #define FDC_CONFIGURE FDC_FIFO_THR | (FDC_POLL_DIS<<4) | (FDC_FIFO_DIS<<5) | (FDC_IMPLIED_SEEK << 6)
  102. #define FDC_MFM_MODE 0x01 /* MFM enable */
  103. #define FDC_SKIP_MODE 0x00 /* skip enable */
  104. #define FDC_TIME_OUT 100000 /* time out */
  105. #define FDC_RW_RETRIES 3 /* read write retries */
  106. #define FDC_CAL_RETRIES 3 /* calibration and seek retries */
  107. /* Disk structure */
  108. typedef struct {
  109. unsigned int size; /* nr of sectors total */
  110. unsigned int sect; /* sectors per track */
  111. unsigned int head; /* nr of heads */
  112. unsigned int track; /* nr of tracks */
  113. unsigned int stretch; /* !=0 means double track steps */
  114. unsigned char gap; /* gap1 size */
  115. unsigned char rate; /* data rate. |= 0x40 for perpendicular */
  116. unsigned char spec1; /* stepping rate, head unload time */
  117. unsigned char fmt_gap;/* gap2 size */
  118. unsigned char hlt; /* head load time */
  119. unsigned char sect_code;/* Sector Size code */
  120. const char * name; /* used only for predefined formats */
  121. } FD_GEO_STRUCT;
  122. /* supported Floppy types (currently only one) */
  123. const static FD_GEO_STRUCT floppy_type[2] = {
  124. { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,16,2,"H1440" }, /* 7 1.44MB 3.5" */
  125. { 0, 0,0, 0,0,0x00,0x00,0x00,0x00, 0,0,NULL }, /* end of table */
  126. };
  127. static FDC_COMMAND_STRUCT cmd; /* global command struct */
  128. /* If the boot drive number is undefined, we assume it's drive 0 */
  129. #ifndef CONFIG_SYS_FDC_DRIVE_NUMBER
  130. #define CONFIG_SYS_FDC_DRIVE_NUMBER 0
  131. #endif
  132. /* Hardware access */
  133. #ifndef CONFIG_SYS_ISA_IO_STRIDE
  134. #define CONFIG_SYS_ISA_IO_STRIDE 1
  135. #endif
  136. #ifndef CONFIG_SYS_ISA_IO_OFFSET
  137. #define CONFIG_SYS_ISA_IO_OFFSET 0
  138. #endif
  139. /* Supporting Functions */
  140. /* reads a Register of the FDC */
  141. unsigned char read_fdc_reg(unsigned int addr)
  142. {
  143. volatile unsigned char *val =
  144. (volatile unsigned char *)(CONFIG_SYS_ISA_IO_BASE_ADDRESS +
  145. (addr * CONFIG_SYS_ISA_IO_STRIDE) +
  146. CONFIG_SYS_ISA_IO_OFFSET);
  147. return val [0];
  148. }
  149. /* writes a Register of the FDC */
  150. void write_fdc_reg(unsigned int addr, unsigned char val)
  151. {
  152. volatile unsigned char *tmp =
  153. (volatile unsigned char *)(CONFIG_SYS_ISA_IO_BASE_ADDRESS +
  154. (addr * CONFIG_SYS_ISA_IO_STRIDE) +
  155. CONFIG_SYS_ISA_IO_OFFSET);
  156. tmp[0]=val;
  157. }
  158. /* waits for an interrupt (polling) */
  159. int wait_for_fdc_int(void)
  160. {
  161. unsigned long timeout;
  162. timeout = FDC_TIME_OUT;
  163. while((read_fdc_reg(FDC_SRA)&0x80)==0) {
  164. timeout--;
  165. udelay(10);
  166. if(timeout==0) /* timeout occurred */
  167. return false;
  168. }
  169. return true;
  170. }
  171. /* reads a byte from the FIFO of the FDC and checks direction and RQM bit
  172. of the MSR. returns -1 if timeout, or byte if ok */
  173. int read_fdc_byte(void)
  174. {
  175. unsigned long timeout;
  176. timeout = FDC_TIME_OUT;
  177. while((read_fdc_reg(FDC_MSR)&0xC0)!=0xC0) {
  178. /* direction out and ready */
  179. udelay(10);
  180. timeout--;
  181. if(timeout==0) /* timeout occurred */
  182. return -1;
  183. }
  184. return read_fdc_reg(FDC_FIFO);
  185. }
  186. /* if the direction of the FIFO is wrong, this routine is used to
  187. empty the FIFO. Should _not_ be used */
  188. int fdc_need_more_output(void)
  189. {
  190. unsigned char c;
  191. while((read_fdc_reg(FDC_MSR)&0xC0)==0xC0) {
  192. c=(unsigned char)read_fdc_byte();
  193. printf("Error: more output: %x\n",c);
  194. }
  195. return true;
  196. }
  197. /* writes a byte to the FIFO of the FDC and checks direction and RQM bit
  198. of the MSR */
  199. int write_fdc_byte(unsigned char val)
  200. {
  201. unsigned long timeout;
  202. timeout = FDC_TIME_OUT;
  203. while((read_fdc_reg(FDC_MSR)&0xC0)!=0x80) {
  204. /* direction in and ready for byte */
  205. timeout--;
  206. udelay(10);
  207. fdc_need_more_output();
  208. if(timeout==0) /* timeout occurred */
  209. return false;
  210. }
  211. write_fdc_reg(FDC_FIFO,val);
  212. return true;
  213. }
  214. /* sets up all FDC commands and issues it to the FDC. If
  215. the command causes direct results (no Execution Phase)
  216. the result is be read as well. */
  217. int fdc_issue_cmd(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)
  218. {
  219. int i;
  220. unsigned long head,track,sect,timeout;
  221. track = pCMD->blnr / (pFG->sect * pFG->head); /* track nr */
  222. sect = pCMD->blnr % (pFG->sect * pFG->head); /* remaining blocks */
  223. head = sect / pFG->sect; /* head nr */
  224. sect = sect % pFG->sect; /* remaining blocks */
  225. sect++; /* sectors are 1 based */
  226. PRINTF("Cmd 0x%02x Track %ld, Head %ld, Sector %ld, Drive %d (blnr %ld)\n",
  227. pCMD->cmd[0],track,head,sect,pCMD->drive,pCMD->blnr);
  228. if(head|=0) { /* max heads = 2 */
  229. pCMD->cmd[DRIVE]=pCMD->drive | 0x04; /* head 1 */
  230. pCMD->cmd[HEAD]=(unsigned char) head; /* head register */
  231. }
  232. else {
  233. pCMD->cmd[DRIVE]=pCMD->drive; /* head 0 */
  234. pCMD->cmd[HEAD]=(unsigned char) head; /* head register */
  235. }
  236. pCMD->cmd[TRACK]=(unsigned char) track; /* track */
  237. switch (pCMD->cmd[COMMAND]) {
  238. case FDC_CMD_READ:
  239. pCMD->cmd[SECTOR]=(unsigned char) sect; /* sector */
  240. pCMD->cmd[SECTOR_SIZE]=pFG->sect_code; /* sector size code */
  241. pCMD->cmd[LAST_TRACK]=pFG->sect; /* End of track */
  242. pCMD->cmd[GAP]=pFG->gap; /* gap */
  243. pCMD->cmd[DTL]=0xFF; /* DTL */
  244. pCMD->cmdlen=FDC_CMD_READ_LEN;
  245. pCMD->cmd[COMMAND]|=(FDC_MFM_MODE<<6); /* set MFM bit */
  246. pCMD->cmd[COMMAND]|=(FDC_SKIP_MODE<<5); /* set Skip bit */
  247. pCMD->resultlen=0; /* result only after execution */
  248. break;
  249. case FDC_CMD_SEEK:
  250. pCMD->cmdlen=FDC_CMD_SEEK_LEN;
  251. pCMD->resultlen=0; /* no result */
  252. break;
  253. case FDC_CMD_CONFIGURE:
  254. pCMD->cmd[CONFIG0]=0;
  255. pCMD->cmd[CONFIG1]=FDC_CONFIGURE; /* FIFO Threshold, Poll, Enable FIFO */
  256. pCMD->cmd[CONFIG2]=FDC_PRE_TRK; /* Precompensation Track */
  257. pCMD->cmdlen=FDC_CMD_CONFIGURE_LEN;
  258. pCMD->resultlen=0; /* no result */
  259. break;
  260. case FDC_CMD_SPECIFY:
  261. pCMD->cmd[SPEC_HUTSRT]=pFG->spec1;
  262. pCMD->cmd[SPEC_HLT]=(pFG->hlt)<<1; /* head load time */
  263. if(pCMD->dma==0)
  264. pCMD->cmd[SPEC_HLT]|=0x1; /* no dma */
  265. pCMD->cmdlen=FDC_CMD_SPECIFY_LEN;
  266. pCMD->resultlen=0; /* no result */
  267. break;
  268. case FDC_CMD_DUMP_REG:
  269. pCMD->cmdlen=FDC_CMD_DUMP_REG_LEN;
  270. pCMD->resultlen=10; /* 10 byte result */
  271. break;
  272. case FDC_CMD_READ_ID:
  273. pCMD->cmd[COMMAND]|=(FDC_MFM_MODE<<6); /* set MFM bit */
  274. pCMD->cmdlen=FDC_CMD_READ_ID_LEN;
  275. pCMD->resultlen=7; /* 7 byte result */
  276. break;
  277. case FDC_CMD_RECALIBRATE:
  278. pCMD->cmd[DRIVE]&=0x03; /* don't set the head bit */
  279. pCMD->cmdlen=FDC_CMD_RECALIBRATE_LEN;
  280. pCMD->resultlen=0; /* no result */
  281. break;
  282. break;
  283. case FDC_CMD_SENSE_INT:
  284. pCMD->cmdlen=FDC_CMD_SENSE_INT_LEN;
  285. pCMD->resultlen=2;
  286. break;
  287. }
  288. for(i=0;i<pCMD->cmdlen;i++) {
  289. /* PRINTF("write cmd%d = 0x%02X\n",i,pCMD->cmd[i]); */
  290. if (write_fdc_byte(pCMD->cmd[i]) == false) {
  291. PRINTF("Error: timeout while issue cmd%d\n",i);
  292. return false;
  293. }
  294. }
  295. timeout=FDC_TIME_OUT;
  296. for(i=0;i<pCMD->resultlen;i++) {
  297. while((read_fdc_reg(FDC_MSR)&0xC0)!=0xC0) {
  298. timeout--;
  299. if(timeout==0) {
  300. PRINTF(" timeout while reading result%d MSR=0x%02X\n",i,read_fdc_reg(FDC_MSR));
  301. return false;
  302. }
  303. }
  304. pCMD->result[i]=(unsigned char)read_fdc_byte();
  305. }
  306. return true;
  307. }
  308. /* selects the drive assigned in the cmd structur and
  309. switches on the Motor */
  310. void select_fdc_drive(FDC_COMMAND_STRUCT *pCMD)
  311. {
  312. unsigned char val;
  313. val=(1<<(4+pCMD->drive))|pCMD->drive|0xC; /* set reset, dma gate and motor bits */
  314. if((read_fdc_reg(FDC_DOR)&val)!=val) {
  315. write_fdc_reg(FDC_DOR,val);
  316. for(val=0;val<255;val++)
  317. udelay(500); /* wait some time to start motor */
  318. }
  319. }
  320. /* switches off the Motor of the specified drive */
  321. void stop_fdc_drive(FDC_COMMAND_STRUCT *pCMD)
  322. {
  323. unsigned char val;
  324. val=(1<<(4+pCMD->drive))|pCMD->drive; /* sets motor bits */
  325. write_fdc_reg(FDC_DOR,(read_fdc_reg(FDC_DOR)&~val));
  326. }
  327. /* issues a recalibrate command, waits for interrupt and
  328. * issues a sense_interrupt */
  329. int fdc_recalibrate(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)
  330. {
  331. pCMD->cmd[COMMAND]=FDC_CMD_RECALIBRATE;
  332. if (fdc_issue_cmd(pCMD, pFG) == false)
  333. return false;
  334. while (wait_for_fdc_int() != true);
  335. pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;
  336. return(fdc_issue_cmd(pCMD,pFG));
  337. }
  338. /* issues a recalibrate command, waits for interrupt and
  339. * issues a sense_interrupt */
  340. int fdc_seek(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)
  341. {
  342. pCMD->cmd[COMMAND]=FDC_CMD_SEEK;
  343. if (fdc_issue_cmd(pCMD, pFG) == false)
  344. return false;
  345. while (wait_for_fdc_int() != true);
  346. pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;
  347. return(fdc_issue_cmd(pCMD,pFG));
  348. }
  349. /* terminates current command, by not servicing the FIFO
  350. * waits for interrupt and fills in the result bytes */
  351. int fdc_terminate(FDC_COMMAND_STRUCT *pCMD)
  352. {
  353. int i;
  354. for(i=0;i<100;i++)
  355. udelay(500); /* wait 500usec for fifo overrun */
  356. while((read_fdc_reg(FDC_SRA)&0x80)==0x00); /* wait as long as no int has occurred */
  357. for(i=0;i<7;i++) {
  358. pCMD->result[i]=(unsigned char)read_fdc_byte();
  359. }
  360. return true;
  361. }
  362. /* reads data from FDC, seek commands are issued automatic */
  363. int fdc_read_data(unsigned char *buffer, unsigned long blocks,FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
  364. {
  365. /* first seek to start address */
  366. unsigned long len,readblk,i,timeout,ii,offset;
  367. unsigned char c,retriesrw,retriescal;
  368. unsigned char *bufferw; /* working buffer */
  369. int sect_size;
  370. int flags;
  371. flags=disable_interrupts(); /* switch off all Interrupts */
  372. select_fdc_drive(pCMD); /* switch on drive */
  373. sect_size=0x080<<pFG->sect_code;
  374. retriesrw=0;
  375. retriescal=0;
  376. offset=0;
  377. if (fdc_seek(pCMD, pFG) == false) {
  378. stop_fdc_drive(pCMD);
  379. if (flags)
  380. enable_interrupts();
  381. return false;
  382. }
  383. if((pCMD->result[STATUS_0]&0x20)!=0x20) {
  384. printf("Seek error Status: %02X\n",pCMD->result[STATUS_0]);
  385. stop_fdc_drive(pCMD);
  386. if (flags)
  387. enable_interrupts();
  388. return false;
  389. }
  390. /* now determine the next seek point */
  391. /* lastblk=pCMD->blnr + blocks; */
  392. /* readblk=(pFG->head*pFG->sect)-(pCMD->blnr%(pFG->head*pFG->sect)); */
  393. readblk=pFG->sect-(pCMD->blnr%pFG->sect);
  394. PRINTF("1st nr of block possible read %ld start %ld\n",readblk,pCMD->blnr);
  395. if(readblk>blocks) /* is end within 1st track */
  396. readblk=blocks; /* yes, correct it */
  397. PRINTF("we read %ld blocks start %ld\n",readblk,pCMD->blnr);
  398. bufferw = &buffer[0]; /* setup working buffer */
  399. do {
  400. retryrw:
  401. len=sect_size * readblk;
  402. pCMD->cmd[COMMAND]=FDC_CMD_READ;
  403. if (fdc_issue_cmd(pCMD, pFG) == false) {
  404. stop_fdc_drive(pCMD);
  405. if (flags)
  406. enable_interrupts();
  407. return false;
  408. }
  409. for (i=0;i<len;i++) {
  410. timeout=FDC_TIME_OUT;
  411. do {
  412. c=read_fdc_reg(FDC_MSR);
  413. if((c&0xC0)==0xC0) {
  414. bufferw[i]=read_fdc_reg(FDC_FIFO);
  415. break;
  416. }
  417. if((c&0xC0)==0x80) { /* output */
  418. PRINTF("Transfer error transferred: at %ld, MSR=%02X\n",i,c);
  419. if(i>6) {
  420. for(ii=0;ii<7;ii++) {
  421. pCMD->result[ii]=bufferw[(i-7+ii)];
  422. } /* for */
  423. }
  424. if(retriesrw++>FDC_RW_RETRIES) {
  425. if (retriescal++>FDC_CAL_RETRIES) {
  426. stop_fdc_drive(pCMD);
  427. if (flags)
  428. enable_interrupts();
  429. return false;
  430. }
  431. else {
  432. PRINTF(" trying to recalibrate Try %d\n",retriescal);
  433. if (fdc_recalibrate(pCMD, pFG) == false) {
  434. stop_fdc_drive(pCMD);
  435. if (flags)
  436. enable_interrupts();
  437. return false;
  438. }
  439. retriesrw=0;
  440. goto retrycal;
  441. } /* else >FDC_CAL_RETRIES */
  442. }
  443. else {
  444. PRINTF("Read retry %d\n",retriesrw);
  445. goto retryrw;
  446. } /* else >FDC_RW_RETRIES */
  447. }/* if output */
  448. timeout--;
  449. } while (true);
  450. } /* for len */
  451. /* the last sector of a track or all data has been read,
  452. * we need to get the results */
  453. fdc_terminate(pCMD);
  454. offset+=(sect_size*readblk); /* set up buffer pointer */
  455. bufferw = &buffer[offset];
  456. pCMD->blnr+=readblk; /* update current block nr */
  457. blocks-=readblk; /* update blocks */
  458. if(blocks==0)
  459. break; /* we are finish */
  460. /* setup new read blocks */
  461. /* readblk=pFG->head*pFG->sect; */
  462. readblk=pFG->sect;
  463. if(readblk>blocks)
  464. readblk=blocks;
  465. retrycal:
  466. /* a seek is necessary */
  467. if (fdc_seek(pCMD, pFG) == false) {
  468. stop_fdc_drive(pCMD);
  469. if (flags)
  470. enable_interrupts();
  471. return false;
  472. }
  473. if((pCMD->result[STATUS_0]&0x20)!=0x20) {
  474. PRINTF("Seek error Status: %02X\n",pCMD->result[STATUS_0]);
  475. stop_fdc_drive(pCMD);
  476. return false;
  477. }
  478. } while (true); /* start over */
  479. stop_fdc_drive(pCMD); /* switch off drive */
  480. if (flags)
  481. enable_interrupts();
  482. return true;
  483. }
  484. /* Scan all drives and check if drive is present and disk is inserted */
  485. int fdc_check_drive(FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
  486. {
  487. int i,drives,state;
  488. /* OK procedure of data book is satisfied.
  489. * trying to get some information over the drives */
  490. state=0; /* no drives, no disks */
  491. for(drives=0;drives<4;drives++) {
  492. pCMD->drive=drives;
  493. select_fdc_drive(pCMD);
  494. pCMD->blnr=0; /* set to the 1st block */
  495. if (fdc_recalibrate(pCMD, pFG) == false)
  496. continue;
  497. if((pCMD->result[STATUS_0]&0x10)==0x10)
  498. continue;
  499. /* ok drive connected check for disk */
  500. state|=(1<<drives);
  501. pCMD->blnr=pFG->size; /* set to the last block */
  502. if (fdc_seek(pCMD, pFG) == false)
  503. continue;
  504. pCMD->blnr=0; /* set to the 1st block */
  505. if (fdc_recalibrate(pCMD, pFG) == false)
  506. continue;
  507. pCMD->cmd[COMMAND]=FDC_CMD_READ_ID;
  508. if (fdc_issue_cmd(pCMD, pFG) == false)
  509. continue;
  510. state|=(0x10<<drives);
  511. }
  512. stop_fdc_drive(pCMD);
  513. for(i=0;i<4;i++) {
  514. PRINTF("Floppy Drive %d %sconnected %sDisk inserted %s\n",i,
  515. ((state&(1<<i))==(1<<i)) ? "":"not ",
  516. ((state&(0x10<<i))==(0x10<<i)) ? "":"no ",
  517. ((state&(0x10<<i))==(0x10<<i)) ? pFG->name : "");
  518. }
  519. pCMD->flags=state;
  520. return true;
  521. }
  522. /**************************************************************************
  523. * int fdc_setup
  524. * setup the fdc according the datasheet
  525. * assuming in PS2 Mode
  526. */
  527. int fdc_setup(int drive, FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
  528. {
  529. int i;
  530. #ifdef CONFIG_SYS_FDC_HW_INIT
  531. fdc_hw_init ();
  532. #endif
  533. /* first, we reset the FDC via the DOR */
  534. write_fdc_reg(FDC_DOR,0x00);
  535. for(i=0; i<255; i++) /* then we wait some time */
  536. udelay(500);
  537. /* then, we clear the reset in the DOR */
  538. pCMD->drive=drive;
  539. select_fdc_drive(pCMD);
  540. /* initialize the CCR */
  541. write_fdc_reg(FDC_CCR,pFG->rate);
  542. /* then initialize the DSR */
  543. write_fdc_reg(FDC_DSR,pFG->rate);
  544. if (wait_for_fdc_int() == false) {
  545. PRINTF("Time Out after writing CCR\n");
  546. return false;
  547. }
  548. /* now issue sense Interrupt and status command
  549. * assuming only one drive present (drive 0) */
  550. pCMD->dma=0; /* we don't use any dma at all */
  551. for(i=0;i<4;i++) {
  552. /* issue sense interrupt for all 4 possible drives */
  553. pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;
  554. if (fdc_issue_cmd(pCMD, pFG) == false) {
  555. PRINTF("Sense Interrupt for drive %d failed\n",i);
  556. }
  557. }
  558. /* issue the configure command */
  559. pCMD->drive=drive;
  560. select_fdc_drive(pCMD);
  561. pCMD->cmd[COMMAND]=FDC_CMD_CONFIGURE;
  562. if (fdc_issue_cmd(pCMD, pFG) == false) {
  563. PRINTF(" configure timeout\n");
  564. stop_fdc_drive(pCMD);
  565. return false;
  566. }
  567. /* issue specify command */
  568. pCMD->cmd[COMMAND]=FDC_CMD_SPECIFY;
  569. if (fdc_issue_cmd(pCMD, pFG) == false) {
  570. PRINTF(" specify timeout\n");
  571. stop_fdc_drive(pCMD);
  572. return false;
  573. }
  574. /* then, we clear the reset in the DOR */
  575. /* fdc_check_drive(pCMD,pFG); */
  576. /* write_fdc_reg(FDC_DOR,0x04); */
  577. return true;
  578. }
  579. /****************************************************************************
  580. * main routine do_fdcboot
  581. */
  582. int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  583. {
  584. FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type;
  585. FDC_COMMAND_STRUCT *pCMD = &cmd;
  586. unsigned long addr,imsize;
  587. #if defined(CONFIG_LEGACY_IMAGE_FORMAT)
  588. image_header_t *hdr; /* used for fdc boot */
  589. #endif
  590. unsigned char boot_drive;
  591. int i,nrofblk;
  592. #if defined(CONFIG_FIT)
  593. const void *fit_hdr = NULL;
  594. #endif
  595. switch (argc) {
  596. case 1:
  597. addr = CONFIG_SYS_LOAD_ADDR;
  598. boot_drive=CONFIG_SYS_FDC_DRIVE_NUMBER;
  599. break;
  600. case 2:
  601. addr = simple_strtoul(argv[1], NULL, 16);
  602. boot_drive=CONFIG_SYS_FDC_DRIVE_NUMBER;
  603. break;
  604. case 3:
  605. addr = simple_strtoul(argv[1], NULL, 16);
  606. boot_drive=simple_strtoul(argv[2], NULL, 10);
  607. break;
  608. default:
  609. return CMD_RET_USAGE;
  610. }
  611. /* setup FDC and scan for drives */
  612. if (fdc_setup(boot_drive, pCMD, pFG) == false) {
  613. printf("\n** Error in setup FDC **\n");
  614. return 1;
  615. }
  616. if (fdc_check_drive(pCMD, pFG) == false) {
  617. printf("\n** Error in check_drives **\n");
  618. return 1;
  619. }
  620. if((pCMD->flags&(1<<boot_drive))==0) {
  621. /* drive not available */
  622. printf("\n** Drive %d not availabe **\n",boot_drive);
  623. return 1;
  624. }
  625. if((pCMD->flags&(0x10<<boot_drive))==0) {
  626. /* no disk inserted */
  627. printf("\n** No disk inserted in drive %d **\n",boot_drive);
  628. return 1;
  629. }
  630. /* ok, we have a valid source */
  631. pCMD->drive=boot_drive;
  632. /* read first block */
  633. pCMD->blnr=0;
  634. if (fdc_read_data((unsigned char *)addr, 1, pCMD, pFG) == false) {
  635. printf("\nRead error:");
  636. for(i=0;i<7;i++)
  637. printf("result%d: 0x%02X\n",i,pCMD->result[i]);
  638. return 1;
  639. }
  640. switch (genimg_get_format ((void *)addr)) {
  641. #if defined(CONFIG_LEGACY_IMAGE_FORMAT)
  642. case IMAGE_FORMAT_LEGACY:
  643. hdr = (image_header_t *)addr;
  644. image_print_contents (hdr);
  645. imsize = image_get_image_size (hdr);
  646. break;
  647. #endif
  648. #if defined(CONFIG_FIT)
  649. case IMAGE_FORMAT_FIT:
  650. fit_hdr = (const void *)addr;
  651. puts ("Fit image detected...\n");
  652. imsize = fit_get_size (fit_hdr);
  653. break;
  654. #endif
  655. default:
  656. puts ("** Unknown image type\n");
  657. return 1;
  658. }
  659. nrofblk=imsize/512;
  660. if((imsize%512)>0)
  661. nrofblk++;
  662. printf("Loading %ld Bytes (%d blocks) at 0x%08lx..\n",imsize,nrofblk,addr);
  663. pCMD->blnr=0;
  664. if (fdc_read_data((unsigned char *)addr, nrofblk, pCMD, pFG) == false) {
  665. /* read image block */
  666. printf("\nRead error:");
  667. for(i=0;i<7;i++)
  668. printf("result%d: 0x%02X\n",i,pCMD->result[i]);
  669. return 1;
  670. }
  671. printf("OK %ld Bytes loaded.\n",imsize);
  672. flush_cache (addr, imsize);
  673. #if defined(CONFIG_FIT)
  674. /* This cannot be done earlier, we need complete FIT image in RAM first */
  675. if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
  676. if (!fit_check_format (fit_hdr)) {
  677. puts ("** Bad FIT image format\n");
  678. return 1;
  679. }
  680. fit_print_contents (fit_hdr);
  681. }
  682. #endif
  683. /* Loading ok, update default load address */
  684. load_addr = addr;
  685. return bootm_maybe_autostart(cmdtp, argv[0]);
  686. }
  687. U_BOOT_CMD(
  688. fdcboot, 3, 1, do_fdcboot,
  689. "boot from floppy device",
  690. "loadAddr drive"
  691. );