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