📄 xd.c.txt
字号:
224
225 return (0);
226 }
227 break;
228 case BLKFLSBUF:
229 if(!suser()) return -EACCES;
230 if(!inode->i_rdev) return -EINVAL;
231 fsync_dev(inode->i_rdev);
232 invalidate_buffers(inode->i_rdev);
233 return 0;
234
235 case BLKRRPART: return (xd_reread_partitions(inode->i_rdev));
236 RO_IOCTLS(inode->i_rdev,arg);
237 }
238 return (-EINVAL);
239 }
240
241 /* xd_release: release the device */
242 static void xd_release (struct inode *inode, struct file *file)
243 {
244 int dev = DEVICE_NR(MINOR(inode->i_rdev));
245
246 if (dev < xd_drives) {
247 sync_dev(dev);
248 xd_access[dev]--;
249 }
250 }
251
252 /* xd_reread_partitions: rereads the partition table from a drive */
253 static int xd_reread_partitions(int dev)
254 {
255 int target = DEVICE_NR(MINOR(dev)),start = target << xd_gendisk.minor_shift,partition;
256
257 cli(); xd_valid[target] = (xd_access[target] != 1); sti();
258 if (xd_valid[target])
259 return (-EBUSY);
260
261 for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) {
262 sync_dev(MAJOR_NR << 8 | start | partition);
263 invalidate_inodes(MAJOR_NR << 8 | start | partition);
264 invalidate_buffers(MAJOR_NR << 8 | start | partition);
265 xd_gendisk.part[start + partition].start_sect = 0;
266 xd_gendisk.part[start + partition].nr_sects = 0;
267 };
268
269 xd_gendisk.part[start].nr_sects = xd_info[target].heads * xd_info[target].cylinders * xd_info[target].sectors;
270 resetup_one_dev(&xd_gendisk,target);
271
272 xd_valid[target] = 1;
273 wake_up(&xd_wait_open);
274
275 return (0);
276 }
277
278 /* xd_readwrite: handle a read/write request */
279 static int xd_readwrite (u_char operation,u_char drive,char *buffer,u_int block,u_int count)
280 {
281 u_char cmdblk[6],sense[4];
282 u_short track,cylinder;
283 u_char head,sector,control,mode,temp;
284
285 #ifdef DEBUG_READWRITE
286 printk("xd_readwrite: operation = %s, drive = %d, buffer = 0x%X, block = %d, count = %d\n",operation == READ ? "read" : "write",drive,buffer,block,count);
287 #endif /* DEBUG_READWRITE */
288
289 control = xd_info[drive].control;
290 while (count) {
291 temp = count < xd_maxsectors ? count : xd_maxsectors;
292
293 track = block / xd_info[drive].sectors;
294 head = track % xd_info[drive].heads;
295 cylinder = track / xd_info[drive].heads;
296 sector = block % xd_info[drive].sectors;
297
298 #ifdef DEBUG_READWRITE
299 printk("xd_readwrite: drive = %d, head = %d, cylinder = %d, sector = %d, count = %d\n",drive,head,cylinder,sector,temp);
300 #endif /* DEBUG_READWRITE */
301
302 mode = xd_setup_dma(operation == READ ? DMA_MODE_READ : DMA_MODE_WRITE,(u_char *)buffer,temp * 0x200);
303 xd_build(cmdblk,operation == READ ? CMD_READ : CMD_WRITE,drive,head,cylinder,sector,temp & 0xFF,control);
304
305 switch (xd_command(cmdblk,mode,(u_char *) buffer,(u_char *) buffer,sense,XD_TIMEOUT)) {
306 case 1: printk("xd_readwrite: timeout, recalibrating drive\n"); xd_recalibrate(drive); return (0);
307 case 2: switch ((sense[0] & 0x30) >> 4) {
308 case 0: printk("xd_readwrite: drive error, code = 0x%X",sense[0] & 0x0F); break;
309 case 1: printk("xd_readwrite: controller error, code = 0x%X",sense[0] & 0x0F); break;
310 case 2: printk("xd_readwrite: command error, code = 0x%X",sense[0] & 0x0F); break;
311 case 3: printk("xd_readwrite: miscellaneous error, code = 0x%X",sense[0] & 0x0F); break;
312 }
313 if (sense[0] & 0x80)
314 printk(" - drive = %d, head = %d, cylinder = %d, sector = %d\n",sense[1] & 0xE0,sense[1] & 0x1F,((sense[2] & 0xC0) << 2) | sense[3],sense[2] & 0x3F);
315 else
316 printk(" - no valid disk address\n");
317 return (0);
318 }
319 count -= temp, buffer += temp * 0x200, block += temp;
320 }
321 return (1);
322 }
323
324 /* xd_recalibrate: recalibrate a given drive and reset controller if necessary */
325 static void xd_recalibrate (u_char drive)
326 {
327 u_char cmdblk[6];
328
329 xd_build(cmdblk,CMD_RECALIBRATE,drive,0,0,0,0,0);
330 if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 8))
331 printk("xd_recalibrate: warning! error recalibrating, controller may be unstable\n");
332 }
333
334 /* xd_interrupt_handler: interrupt service routine */
335 static void xd_interrupt_handler (int unused)
336 {
337 if (inb(XD_STATUS) & STAT_INTERRUPT) { /* check if it was our device */
338 #ifdef DEBUG_OTHER
339 printk("xd_interrupt_handler: interrupt detected\n");
340 #endif /* DEBUG_OTHER */
341 outb(0,XD_CONTROL); /* acknowledge interrupt */
342 wake_up(&xd_wait_int); /* and wake up sleeping processes */
343 }
344 else
345 printk("xd_interrupt_handler: unexpected interrupt\n");
346 }
347
348 /* xd_dma: set up the DMA controller for a data transfer */
349 static u_char xd_setup_dma (u_char mode,u_char *buffer,u_int count)
350 {
351 if (buffer < ((u_char *) 0x1000000 - count)) { /* transfer to address < 16M? */
352 if (((u_int) buffer & 0xFFFF0000) != ((u_int) buffer + count) & 0xFFFF0000) {
353 #ifdef DEBUG_OTHER
354 printk("xd_setup_dma: using PIO, transfer overlaps 64k boundary\n");
355 #endif /* DEBUG_OTHER */
356 return (PIO_MODE);
357 }
358 disable_dma(xd_dma);
359 clear_dma_ff(xd_dma);
360 set_dma_mode(xd_dma,mode);
361 set_dma_addr(xd_dma,(u_int) buffer);
362 set_dma_count(xd_dma,count);
363
364 return (DMA_MODE); /* use DMA and INT */
365 }
366 #ifdef DEBUG_OTHER
367 printk("xd_setup_dma: using PIO, cannot DMA above 16 meg\n");
368 #endif /* DEBUG_OTHER */
369 return (PIO_MODE);
370 }
371
372 /* xd_build: put stuff into an array in a format suitable for the controller */
373 static u_char *xd_build (u_char *cmdblk,u_char command,u_char drive,u_char head,u_short cylinder,u_char sector,u_char count,u_char control)
374 {
375 cmdblk[0] = command;
376 cmdblk[1] = ((drive & 0x07) << 5) | (head & 0x1F);
377 cmdblk[2] = ((cylinder & 0x300) >> 2) | (sector & 0x3F);
378 cmdblk[3] = cylinder & 0xFF;
379 cmdblk[4] = count;
380 cmdblk[5] = control;
381
382 return (cmdblk);
383 }
384
385 /* xd_waitport: waits until port & mask == flags or a timeout occurs. return 1 for a timeout */
386 static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long timeout)
387 {
388 u_long expiry = jiffies + timeout;
389
390 while (((inb(port) & mask) != flags) && (jiffies < expiry))
391 ;
392
393 return (jiffies >= expiry);
394 }
395
396 /* xd_command: handle all data transfers necessary for a single command */
397 static u_int xd_command (u_char *command,u_char mode,u_char *indata,u_char *outdata,u_char *sense,u_long timeout)
398 {
399 u_char cmdblk[6],csb,complete = 0;
400
401 #ifdef DEBUG_COMMAND
402 printk("xd_command: command = 0x%X, mode = 0x%X, indata = 0x%X, outdata = 0x%X, sense = 0x%X\n",command,mode,indata,outdata,sense);
403 #endif /* DEBUG_COMMAND */
404
405 outb(0,XD_SELECT);
406 outb(mode,XD_CONTROL);
407
408 if (xd_waitport(XD_STATUS,STAT_SELECT,STAT_SELECT,timeout))
409 return (1);
410
411 while (!complete) {
412 if (xd_waitport(XD_STATUS,STAT_READY,STAT_READY,timeout))
413 return (1);
414 switch (inb(XD_STATUS) & (STAT_COMMAND | STAT_INPUT)) {
415 case 0: if (mode == DMA_MODE) {
416 enable_dma(xd_dma);
417 sleep_on(&xd_wait_int);
418 disable_dma(xd_dma);
419 }
420 else
421 outb(outdata ? *outdata++ : 0,XD_DATA);
422 break;
423 case STAT_INPUT: if (mode == DMA_MODE) {
424 enable_dma(xd_dma);
425 sleep_on(&xd_wait_int);
426 disable_dma(xd_dma);
427 }
428 else
429 if (indata)
430 *indata++ = inb(XD_DATA);
431 else
432 inb(XD_DATA);
433 break;
434 case STAT_COMMAND: outb(command ? *command++ : 0,XD_DATA); break;
435 case STAT_COMMAND
436 | STAT_INPUT: complete = 1; break;
437 }
438 }
439 csb = inb(XD_DATA);
440
441 if (xd_waitport(XD_STATUS,0,STAT_SELECT,timeout)) /* wait until deselected */
442 return (1);
443
444 if (csb & CSB_ERROR) { /* read sense data if error */
445 xd_build(cmdblk,CMD_SENSE,(csb & CSB_LUN) >> 5,0,0,0,0,0);
446 if (xd_command(cmdblk,0,sense,0,0,XD_TIMEOUT))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -