floppy.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. */
  8. #include <rtthread.h>
  9. #include <rtdevice.h>
  10. #include <rthw.h>
  11. #include <bsp.h>
  12. typedef rt_uint8_t u8;
  13. typedef rt_uint16_t u16;
  14. typedef rt_uint32_t u32;
  15. typedef rt_int8_t s8;
  16. typedef rt_int16_t s16;
  17. typedef rt_int32_t s32;
  18. #define OUTB(v,p) outb(p,v)
  19. #include "floppy.h"
  20. #include "dma.h"
  21. #define SECTOR_SIZE 512
  22. #define panic(str,...) do { rt_kprintf("panic::" str,##__VA_ARGS__); while(1); } while(0)
  23. #define _local_irq_save(level) level = rt_hw_interrupt_disable()
  24. #define _local_irq_restore(level) rt_hw_interrupt_enable(level)
  25. static u8 floppy_buffer[512]; /* 软盘高速缓冲区地址指针 */
  26. #define MAX_REPLIES 7
  27. static u8 floppy_reply_buffer[MAX_REPLIES]; /* 软驱回应缓冲区 */
  28. #define ST0 (floppy_reply_buffer[0]) /* 软驱回应0号字节 */
  29. #define ST1 (floppy_reply_buffer[1]) /* 软驱回应1号字节 */
  30. #define ST2 (floppy_reply_buffer[2]) /* 软驱回应2号字节 */
  31. #define ST3 (floppy_reply_buffer[3]) /* 软驱回应3号字节 */
  32. static char *floppy_inc_name; /* 软驱型号名 */
  33. static char *floppy_type;
  34. static u32 floppy_motor=0; /* 软驱马达状态字节 */
  35. static u32 floppy_size =0;
  36. /**********************功能函数***************************/
  37. static void floppy_result(void); /* 获得软驱响应状态 */
  38. static u32 floppy_sendbyte(u32); /* 向软驱控制寄存器发送一个控制字节 */
  39. static u32 floppy_getbyte(void); /* 从软驱数据寄存器得到一个数据字节 */
  40. static u32 floppy_get_info(void); /* 得到软驱信息 */
  41. static void floppy_motorOn(void); /* 打开软驱马达 */
  42. static void floppy_motorOff(void); /* 关闭软驱马达 */
  43. static void floppy_setmode(void); /* 软驱模式设置 */
  44. static void block_to_hts(u32, u32*, u32*, u32*); /* 逻辑块转为磁盘头、磁道号和扇区号 */
  45. static void floppy_setupDMA(void); /* 设置软驱DMA通道 */
  46. static void floppy_read_cmd(u32 blk); /* 从软盘上读取指定的逻辑块到缓冲区 */
  47. void floppy_result(void)
  48. {
  49. u8 stat, i,count;
  50. i=0;
  51. for(count=0; count<0xFF; count++)
  52. {
  53. stat = inb( FD_STATUS ) & (STATUS_READY|STATUS_DIR|STATUS_BUSY); //读取状态寄存器
  54. if (stat == STATUS_READY)
  55. return;
  56. if (stat == (STATUS_READY|STATUS_DIR|STATUS_BUSY))
  57. {
  58. if(i>7) break;
  59. floppy_reply_buffer[i++]=inb_p(FD_DATA);
  60. }
  61. }
  62. panic("Get floppy status times out !\n");
  63. }
  64. u32 floppy_sendbyte( u32 value )
  65. {
  66. u8 stat, i;
  67. for ( i = 0; i < 128; i++ ) {
  68. stat = inb( FD_STATUS ) & (STATUS_READY|STATUS_DIR); //读取状态寄存器
  69. if ( stat == STATUS_READY )
  70. {
  71. OUTB( value ,FD_DATA); //将参数写入数据寄存器
  72. return 1;
  73. }
  74. io_delay(); // 作一些延迟
  75. }
  76. return 0;
  77. }
  78. u32 floppy_getbyte(void)
  79. {
  80. u8 stat, i;
  81. for ( i = 0; i < 128; i++ ) {
  82. stat = inb( FD_STATUS ) & (STATUS_READY|STATUS_DIR|STATUS_BUSY); //读取状态寄存器
  83. if (stat == STATUS_READY)
  84. return -1;
  85. if ( stat == 0xD0 )
  86. return inb(FD_DATA);
  87. io_delay();
  88. }
  89. return 0;
  90. }
  91. u32 floppy_get_info(void)
  92. {
  93. u32 i;
  94. u8 CmType, FdType;
  95. floppy_sendbyte(0x10);
  96. i = floppy_getbyte();
  97. switch (i)
  98. {
  99. case 0x80: floppy_inc_name = "NEC765A controller"; break;
  100. case 0x90: floppy_inc_name = "NEC765B controller"; break;
  101. default: floppy_inc_name = "Enhanced controller"; break;
  102. }
  103. CmType = readcmos(0x10); //read floppy type from cmos
  104. FdType = (CmType>>4) & 0x07;
  105. if ( FdType == 0 )
  106. panic("Floppy driver not found!");
  107. switch( FdType )
  108. {
  109. case 0x02: // 1.2MB
  110. floppy_type = "1.2MB";
  111. floppy_size = 2458*512;
  112. break;
  113. case 0x04: // 1.44MB 标准软盘
  114. floppy_type = "1.44MB";
  115. floppy_size = 2880*512;
  116. break;
  117. case 0x05: // 2.88MB
  118. floppy_type = "2.88MB";
  119. floppy_size = 2*2880*512;
  120. break;
  121. }
  122. return 1;
  123. }
  124. void floppy_motorOn( void )
  125. {
  126. u32 eflags;
  127. if (!floppy_motor)
  128. {
  129. _local_irq_save(eflags);
  130. OUTB(28,FD_DOR);
  131. floppy_motor = 1;
  132. _local_irq_restore(eflags);
  133. }
  134. return;
  135. }
  136. void floppy_motorOff( void )
  137. {
  138. u32 eflags;
  139. if (floppy_motor)
  140. {
  141. _local_irq_save(eflags);
  142. OUTB(12,FD_DOR);
  143. floppy_motor = 0;
  144. _local_irq_restore(eflags);
  145. }
  146. return;
  147. }
  148. void floppy_setmode(void)
  149. {
  150. floppy_sendbyte (FD_SPECIFY);
  151. floppy_sendbyte (0xcf);
  152. floppy_sendbyte (0x06);
  153. OUTB (0,FD_DCR);
  154. }
  155. void block_to_hts(u32 block, u32 *head, u32 *track, u32 *sector )
  156. {
  157. *head = ( block % ( 18 * 2 ) ) /18;
  158. *track = block / ( 18 * 2 );
  159. *sector = block % 18 + 1;
  160. }
  161. void floppy_setupDMA(void)
  162. {
  163. u32 eflags;
  164. _local_irq_save(eflags);
  165. DisableDma(2);
  166. ClearDmaFF(2);
  167. SetDmaMode(2,DMA_MODE_READ);
  168. SetDmaAddr(2,(unsigned long)floppy_buffer);
  169. SetDmaCount(2,512);
  170. EnableDma(2);
  171. _local_irq_restore(eflags);
  172. }
  173. void floppy_read_cmd(u32 blk)
  174. {
  175. u32 head;
  176. u32 track;
  177. u32 sector;
  178. block_to_hts(blk,&head,&track,&sector);
  179. floppy_motorOn();
  180. io_delay();
  181. floppy_setupDMA();
  182. io_delay();
  183. floppy_setmode();
  184. io_delay();
  185. floppy_sendbyte (FD_READ); //send read command
  186. floppy_sendbyte (head*4 + 0);
  187. floppy_sendbyte (track); /* Cylinder */
  188. floppy_sendbyte (head); /* Head */
  189. floppy_sendbyte (sector); /* Sector */
  190. floppy_sendbyte (2); /* 0=128, 1=256, 2=512, 3=1024, ... */
  191. floppy_sendbyte (18);
  192. //floppy_sendbyte (sector+secs-1); /* Last sector in track:here are sectors count */
  193. floppy_sendbyte (0x1B);
  194. floppy_sendbyte (0xff);
  195. return;
  196. }
  197. static struct rt_device devF;
  198. static struct rt_mutex lock;
  199. static struct rt_semaphore sem;
  200. /* RT-Thread device interface */
  201. static rt_err_t rt_floppy_init_internal(rt_device_t dev)
  202. {
  203. return RT_EOK;
  204. }
  205. static rt_err_t rt_floppy_open(rt_device_t dev, rt_uint16_t oflag)
  206. {
  207. return RT_EOK;
  208. }
  209. static rt_err_t rt_floppy_close(rt_device_t dev)
  210. {
  211. return RT_EOK;
  212. }
  213. /* position: block page address, not bytes address
  214. * buffer:
  215. * size : how many blocks
  216. */
  217. static rt_ssize_t rt_floppy_read(rt_device_t device, rt_off_t position, void *buffer, rt_size_t size)
  218. {
  219. rt_size_t doSize = size;
  220. rt_mutex_take(&lock, RT_WAITING_FOREVER);
  221. while(size>0)
  222. {
  223. floppy_read_cmd(position);
  224. rt_sem_take(&sem, RT_WAITING_FOREVER); /* waiting isr sem forever */
  225. floppy_result();
  226. io_delay();
  227. if(ST1 != 0 || ST2 != 0)
  228. {
  229. panic("ST0 %d ST1 %d ST2 %d\n",ST0,ST1,ST2);
  230. }
  231. rt_memcpy(buffer, floppy_buffer, 512);
  232. floppy_motorOff();
  233. io_delay();
  234. position += 1;
  235. size -= 1;
  236. }
  237. rt_mutex_release(&lock);
  238. return doSize;
  239. }
  240. /* position: block page address, not bytes address
  241. * buffer:
  242. * size : how many blocks
  243. */
  244. static rt_ssize_t rt_floppy_write(rt_device_t device, rt_off_t position, const void *buffer, rt_size_t size)
  245. {
  246. rt_mutex_take(&lock, RT_WAITING_FOREVER);
  247. panic("FIXME:I don't know how!\n");
  248. rt_mutex_release(&lock);
  249. return size;
  250. }
  251. static rt_err_t rt_floppy_control(rt_device_t dev, int cmd, void *args)
  252. {
  253. RT_ASSERT(dev != RT_NULL);
  254. if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
  255. {
  256. struct rt_device_blk_geometry *geometry;
  257. geometry = (struct rt_device_blk_geometry *)args;
  258. if (geometry == RT_NULL) return -RT_ERROR;
  259. geometry->bytes_per_sector = SECTOR_SIZE;
  260. geometry->block_size = SECTOR_SIZE;
  261. geometry->sector_count = floppy_size / SECTOR_SIZE;
  262. }
  263. return RT_EOK;
  264. }
  265. static void rt_floppy_isr(int vector, void* param)
  266. {
  267. (void)vector;
  268. (void)param;
  269. rt_sem_release(&sem);
  270. }
  271. void rt_floppy_init(void)
  272. {
  273. struct rt_device *device;
  274. rt_mutex_init(&lock,"fdlock", RT_IPC_FLAG_PRIO);
  275. rt_sem_init(&sem, "fdsem", 0, RT_IPC_FLAG_FIFO);
  276. rt_hw_interrupt_install(FLOPPY_IRQ, rt_floppy_isr, RT_NULL, "floppy");
  277. rt_hw_interrupt_umask(FLOPPY_IRQ);
  278. floppy_get_info();
  279. rt_kprintf("Floppy Inc : %s Floppy Type : %s\n",floppy_inc_name,floppy_type);
  280. device = &(devF);
  281. device->type = RT_Device_Class_Block;
  282. device->init = rt_floppy_init_internal;
  283. device->open = rt_floppy_open;
  284. device->close = rt_floppy_close;
  285. device->read = rt_floppy_read;
  286. device->write = rt_floppy_write;
  287. device->control = rt_floppy_control;
  288. device->user_data = RT_NULL;
  289. rt_device_register(device, "floppy",
  290. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
  291. }