⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xd.c.txt

📁 Linux块设备驱动分析与模拟实现
💻 TXT
📖 第 1 页 / 共 3 页
字号:
447                         printk("xd_command: warning! sense command failed!\n");
448         }
449 
450 #ifdef DEBUG_COMMAND
451         printk("xd_command: completed with csb = 0x%X\n",csb);
452 #endif /* DEBUG_COMMAND */
453 
454         return (csb & CSB_ERROR);
455 }
456 
457 static u_char xd_initdrives (void (*init_drive)(u_char drive))
458 {
459         u_char cmdblk[6],i,count = 0;
460 
461         for (i = 0; i < XD_MAXDRIVES; i++) {
462                 xd_build(cmdblk,CMD_TESTREADY,i,0,0,0,0,0);
463                 if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2)) {
464                         init_drive(count);
465                         count++;
466                 }
467         }
468         return (count);
469 }
470 
471 static void xd_dtc_init_controller (u_char *address)
472 {
473         switch ((u_long) address) {
474                 case 0xC8000:   xd_iobase = 0x320; break;
475                 case 0xCA000:   xd_iobase = 0x324; break;
476                 default:        printk("xd_dtc_init_controller: unsupported BIOS address %p\n",address);
477                                 xd_iobase = 0x320; break;
478         }
479         xd_irq = 5;                     /* the IRQ _can_ be changed on this card, but requires a hardware mod */
480         xd_dma = 3;
481         xd_maxsectors = 0x01;           /* my card seems to have trouble doing multi-block transfers? */
482 
483         outb(0,XD_RESET);               /* reset the controller */
484 }
485 
486 static void xd_dtc_init_drive (u_char drive)
487 {
488         u_char cmdblk[6],buf[64];
489 
490         xd_build(cmdblk,CMD_DTCGETGEOM,drive,0,0,0,0,0);
491         if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
492                 xd_info[drive].heads = buf[0x0A];                       /* heads */
493                 xd_info[drive].cylinders = ((u_short *) (buf))[0x04];   /* cylinders */
494                 xd_info[drive].sectors = 17;                            /* sectors */
495 #if 0
496                 xd_info[drive].rwrite = ((u_short *) (buf + 1))[0x05];  /* reduced write */
497                 xd_info[drive].precomp = ((u_short *) (buf + 1))[0x06]; /* write precomp */
498                 xd_info[drive].ecc = buf[0x0F];                         /* ecc length */
499 #endif /* 0 */
500                 xd_info[drive].control = 0;                             /* control byte */
501 
502                 xd_setparam(CMD_DTCSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,((u_short *) (buf + 1))[0x05],((u_short *) (buf + 1))[0x06],buf[0x0F]);
503                 xd_build(cmdblk,CMD_DTCSETSTEP,drive,0,0,0,0,7);
504                 if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))
505                         printk("xd_dtc_init_drive: error setting step rate for drive %d\n",drive);
506         }
507         else
508                 printk("xd_dtc_init_drive: error reading geometry for drive %d\n",drive);
509 }
510 
511 static void xd_wd_init_controller (u_char *address)
512 {
513         switch ((u_long) address) {
514                 case 0xC8000:   xd_iobase = 0x320; break;
515                 case 0xCA000:   xd_iobase = 0x324; break;
516                 case 0xCC000:   xd_iobase = 0x328; break;
517                 case 0xCE000:   xd_iobase = 0x32C; break;
518                 case 0xD0000:   xd_iobase = 0x328; break;
519                 case 0xD8000:   xd_iobase = 0x32C; break;
520                 default:        printk("xd_wd_init_controller: unsupported BIOS address %p\n",address);
521                                 xd_iobase = 0x320; break;
522         }
523         xd_irq = 5;                     /* don't know how to auto-detect this yet */
524         xd_dma = 3;
525         xd_maxsectors = 0x01;           /* this one doesn't wrap properly either... */
526 
527         /* outb(0,XD_RESET); */         /* reset the controller */
528 }
529 
530 static void xd_wd_init_drive (u_char drive)
531 {
532         u_char cmdblk[6],buf[0x200];
533 
534         xd_build(cmdblk,CMD_READ,drive,0,0,0,1,0);
535         if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
536                 xd_info[drive].heads = buf[0x1AF];                              /* heads */
537                 xd_info[drive].cylinders = ((u_short *) (buf + 1))[0xD6];       /* cylinders */
538                 xd_info[drive].sectors = 17;                                    /* sectors */
539 #if 0
540                 xd_info[drive].rwrite = ((u_short *) (buf))[0xD8];              /* reduced write */
541                 xd_info[drive].wprecomp = ((u_short *) (buf))[0xDA];            /* write precomp */
542                 xd_info[drive].ecc = buf[0x1B4];                                /* ecc length */
543 #endif /* 0 */
544                 xd_info[drive].control = buf[0x1B5];                            /* control byte */
545 
546                 xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,((u_short *) (buf))[0xD8],((u_short *) (buf))[0xDA],buf[0x1B4]);
547         }
548         else
549                 printk("xd_wd_init_drive: error reading geometry for drive %d\n",drive);        
550 }
551 
552 static void xd_seagate_init_controller (u_char *address)
553 {
554         switch ((u_long) address) {
555                 case 0xC8000:   xd_iobase = 0x320; break;
556                 case 0xD0000:   xd_iobase = 0x324; break;
557                 case 0xD8000:   xd_iobase = 0x328; break;
558                 case 0xE0000:   xd_iobase = 0x32C; break;
559                 default:        printk("xd_seagate_init_controller: unsupported BIOS address %p\n",address);
560                                 xd_iobase = 0x320; break;
561         }
562         xd_irq = 5;                     /* the IRQ and DMA channel are fixed on the Seagate controllers */
563         xd_dma = 3;
564         xd_maxsectors = 0x40;
565 
566         outb(0,XD_RESET);               /* reset the controller */
567 }
568 
569 static void xd_seagate_init_drive (u_char drive)
570 {
571         u_char cmdblk[6],buf[0x200];
572 
573         xd_build(cmdblk,CMD_ST11GETGEOM,drive,0,0,0,1,0);
574         if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
575                 xd_info[drive].heads = buf[0x04];                               /* heads */
576                 xd_info[drive].cylinders = (buf[0x02] << 8) | buf[0x03];        /* cylinders */
577                 xd_info[drive].sectors = buf[0x05];                             /* sectors */
578                 xd_info[drive].control = 0;                                     /* control byte */
579         }
580         else
581                 printk("xd_seagate_init_drive: error reading geometry from drive %d\n",drive);
582 }
583 
584 /* Omti support courtesy Dirk Melchers */
585 static void xd_omti_init_controller (u_char *address)
586 {
587         switch ((u_long) address) {
588                 case 0xC8000:   xd_iobase = 0x320; break;
589                 case 0xD0000:   xd_iobase = 0x324; break;
590                 case 0xD8000:   xd_iobase = 0x328; break;
591                 case 0xE0000:   xd_iobase = 0x32C; break;
592                 default:        printk("xd_omti_init_controller: unsupported BIOS address %p\n",address);
593                                 xd_iobase = 0x320; break;
594         }
595         
596         xd_irq = 5;                     /* the IRQ and DMA channel are fixed on the Omti controllers */
597         xd_dma = 3;
598         xd_maxsectors = 0x40;
599 
600         outb(0,XD_RESET);               /* reset the controller */
601 }
602 
603 static void xd_omti_init_drive (u_char drive)
604 {
605         /* gets infos from drive */
606         xd_override_init_drive(drive);
607 
608         /* set other parameters, Hardcoded, not that nice :-) */
609         xd_info[drive].control = 2;
610 }
611 
612 /* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads
613    etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */
614 static void xd_override_init_drive (u_char drive)
615 {
616         u_short min[] = { 0,0,0 },max[] = { 16,1024,64 },test[] = { 0,0,0 };
617         u_char cmdblk[6],i;
618 
619         for (i = 0; i < 3; i++) {
620                 while (min[i] != max[i] - 1) {
621                         test[i] = (min[i] + max[i]) / 2;
622                         xd_build(cmdblk,CMD_SEEK,drive,(u_char) test[0],(u_short) test[1],(u_char) test[2],0,0);
623                         if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))
624                                 min[i] = test[i];
625                         else
626                                 max[i] = test[i];
627                 }
628                 test[i] = min[i];
629         }
630         xd_info[drive].heads = (u_char) min[0] + 1;
631         xd_info[drive].cylinders = (u_short) min[1] + 1;
632         xd_info[drive].sectors = (u_char) min[2] + 1;
633         xd_info[drive].control = 0;
634 }
635 
636 /* xd_setup: initialise from command line parameters */
637 void xd_setup (char *command,int *integers)
638 {
639         xd_override = 1;
640 
641         xd_type = integers[1];
642         xd_irq = integers[2];
643         xd_iobase = integers[3];
644         xd_dma = integers[4];
645 
646         xd_maxsectors = 0x01;
647 }
648 
649 /* xd_setparam: set the drive characteristics */
650 static void xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc)
651 {
652         u_char cmdblk[14];
653 
654         xd_build(cmdblk,command,drive,0,0,0,0,0);
655         cmdblk[6] = (u_char) (cylinders >> 8) & 0x03;
656         cmdblk[7] = (u_char) (cylinders & 0xFF);
657         cmdblk[8] = heads & 0x1F;
658         cmdblk[9] = (u_char) (rwrite >> 8) & 0x03;
659         cmdblk[10] = (u_char) (rwrite & 0xFF);
660         cmdblk[11] = (u_char) (wprecomp >> 8) & 0x03;
661         cmdblk[12] = (u_char) (wprecomp & 0xFF);
662         cmdblk[13] = ecc;
663 
664         if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))
665                 printk("xd_setparam: error setting characteristics for drive %d\n",drive);
666 }
667 
668 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -