📄 xd.c
字号:
xd_maxsectors = 0x01; /* this one doesn't wrap properly either... */ outb(0,XD_RESET); /* reset the controller */ xd_timer.expires = jiffies + XD_INIT_DISK_DELAY; add_timer(&xd_timer); sleep_on(&xdc_wait);}static void __init xd_wd_init_drive (u_char drive){ /* values from controller's BIOS - BIOS may be disabled */ static u_short geometry_table[][4] = { {0x264,4,0x1C2,0x1C2}, /* common part */ {0x132,4,0x099,0x0}, {0x267,2,0x1C2,0x1C2}, {0x267,4,0x1C2,0x1C2}, {0x334,6,0x335,0x335}, /* 1004 series RLL */ {0x30E,4,0x30F,0x3DC}, {0x30E,2,0x30F,0x30F}, {0x267,4,0x268,0x268}, {0x3D5,5,0x3D6,0x3D6}, /* 1002 series RLL */ {0x3DB,7,0x3DC,0x3DC}, {0x264,4,0x265,0x265}, {0x267,4,0x268,0x268}}; u_char cmdblk[6],buf[0x200]; u_char n = 0,rll,jumper_state,use_jumper_geo; u_char wd_1002 = (xd_sigs[xd_type].string[7] == '6'); jumper_state = ~(inb(0x322)); if (jumper_state & 0x40) xd_irq = 9; rll = (jumper_state & 0x30) ? (0x04 << wd_1002) : 0; xd_build(cmdblk,CMD_READ,drive,0,0,0,1,0); if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) { xd_info[drive].heads = buf[0x1AF]; /* heads */ xd_info[drive].cylinders = ((u_short *) (buf + 1))[0xD6]; /* cylinders */ xd_info[drive].sectors = 17; /* sectors */ if (xd_geo[3*drive]) xd_manual_geo_set(drive);#if 0 xd_info[drive].rwrite = ((u_short *) (buf))[0xD8]; /* reduced write */ xd_info[drive].wprecomp = ((u_short *) (buf))[0xDA]; /* write precomp */ xd_info[drive].ecc = buf[0x1B4]; /* ecc length */#endif /* 0 */ xd_info[drive].control = buf[0x1B5]; /* control byte */ use_jumper_geo = !(xd_info[drive].heads) || !(xd_info[drive].cylinders); if (xd_geo[3*drive]) { xd_manual_geo_set(drive); xd_info[drive].control = rll ? 7 : 5; } else if (use_jumper_geo) { n = (((jumper_state & 0x0F) >> (drive << 1)) & 0x03) | rll; xd_info[drive].cylinders = geometry_table[n][0]; xd_info[drive].heads = (u_char)(geometry_table[n][1]); xd_info[drive].control = rll ? 7 : 5;#if 0 xd_info[drive].rwrite = geometry_table[n][2]; xd_info[drive].wprecomp = geometry_table[n][3]; xd_info[drive].ecc = 0x0B;#endif /* 0 */ } if (!wd_1002) { if (use_jumper_geo) xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders, geometry_table[n][2],geometry_table[n][3],0x0B); else xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders, ((u_short *) (buf))[0xD8],((u_short *) (buf))[0xDA],buf[0x1B4]); } /* 1002 based RLL controler requests converted addressing, but reports physical (physical 26 sec., logical 17 sec.) 1004 based ???? */ if (rll & wd_1002) { if ((xd_info[drive].cylinders *= 26, xd_info[drive].cylinders /= 17) > 1023) xd_info[drive].cylinders = 1023; /* 1024 ? */#if 0 xd_info[drive].rwrite *= 26; xd_info[drive].rwrite /= 17; xd_info[drive].wprecomp *= 26 xd_info[drive].wprecomp /= 17;#endif /* 0 */ } } else printk("xd_wd_init_drive: error reading geometry for xd%c\n",'a'+drive); }static void __init xd_seagate_init_controller (unsigned int address){ switch (address) { case 0x00000: case 0xC8000: break; /*initial: 0x320 */ case 0xD0000: xd_iobase = 0x324; break; case 0xD8000: xd_iobase = 0x328; break; case 0xE0000: xd_iobase = 0x32C; break; default: printk("xd_seagate_init_controller: unsupported BIOS address %06x\n",address); break; } xd_maxsectors = 0x40; outb(0,XD_RESET); /* reset the controller */}static void __init xd_seagate_init_drive (u_char drive){ u_char cmdblk[6],buf[0x200]; xd_build(cmdblk,CMD_ST11GETGEOM,drive,0,0,0,1,0); if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) { xd_info[drive].heads = buf[0x04]; /* heads */ xd_info[drive].cylinders = (buf[0x02] << 8) | buf[0x03]; /* cylinders */ xd_info[drive].sectors = buf[0x05]; /* sectors */ xd_info[drive].control = 0; /* control byte */ } else printk("xd_seagate_init_drive: error reading geometry from xd%c\n", 'a'+drive);}/* Omti support courtesy Dirk Melchers */static void __init xd_omti_init_controller (unsigned int address){ switch (address) { case 0x00000: case 0xC8000: break; /*initial: 0x320 */ case 0xD0000: xd_iobase = 0x324; break; case 0xD8000: xd_iobase = 0x328; break; case 0xE0000: xd_iobase = 0x32C; break; default: printk("xd_omti_init_controller: unsupported BIOS address %06x\n",address); break; } xd_maxsectors = 0x40; outb(0,XD_RESET); /* reset the controller */}static void __init xd_omti_init_drive (u_char drive){ /* gets infos from drive */ xd_override_init_drive(drive); /* set other parameters, Hardcoded, not that nice :-) */ xd_info[drive].control = 2;}/* Xebec support (AK) */static void __init xd_xebec_init_controller (unsigned int address){/* iobase may be set manually in range 0x300 - 0x33C irq may be set manually to 2(9),3,4,5,6,7 dma may be set manually to 1,2,3 (How to detect them ???)BIOS address may be set manually in range 0x0 - 0xF8000If you need non-standard settings use the xd=... command */ switch (address) { case 0x00000: case 0xC8000: /* initially: xd_iobase==0x320 */ case 0xD0000: case 0xD2000: case 0xD4000: case 0xD6000: case 0xD8000: case 0xDA000: case 0xDC000: case 0xDE000: case 0xE0000: break; default: printk("xd_xebec_init_controller: unsupported BIOS address %06x\n",address); break; } xd_maxsectors = 0x01; outb(0,XD_RESET); /* reset the controller */ xd_timer.expires = jiffies + XD_INIT_DISK_DELAY; add_timer(&xd_timer); sleep_on(&xdc_wait);}static void __init xd_xebec_init_drive (u_char drive){ /* values from controller's BIOS - BIOS chip may be removed */ static u_short geometry_table[][5] = { {0x132,4,0x080,0x080,0x7}, {0x132,4,0x080,0x080,0x17}, {0x264,2,0x100,0x100,0x7}, {0x264,2,0x100,0x100,0x17}, {0x132,8,0x080,0x080,0x7}, {0x132,8,0x080,0x080,0x17}, {0x264,4,0x100,0x100,0x6}, {0x264,4,0x100,0x100,0x17}, {0x2BC,5,0x2BC,0x12C,0x6}, {0x3A5,4,0x3A5,0x3A5,0x7}, {0x26C,6,0x26C,0x26C,0x7}, {0x200,8,0x200,0x100,0x17}, {0x400,5,0x400,0x400,0x7}, {0x400,6,0x400,0x400,0x7}, {0x264,8,0x264,0x200,0x17}, {0x33E,7,0x33E,0x200,0x7}}; u_char n; n = inb(XD_JUMPER) & 0x0F; /* BIOS's drive number: same geometry is assumed for BOTH drives */ if (xd_geo[3*drive]) xd_manual_geo_set(drive); else { xd_info[drive].heads = (u_char)(geometry_table[n][1]); /* heads */ xd_info[drive].cylinders = geometry_table[n][0]; /* cylinders */ xd_info[drive].sectors = 17; /* sectors */#if 0 xd_info[drive].rwrite = geometry_table[n][2]; /* reduced write */ xd_info[drive].precomp = geometry_table[n][3] /* write precomp */ xd_info[drive].ecc = 0x0B; /* ecc length */#endif /* 0 */ } xd_info[drive].control = geometry_table[n][4]; /* control byte */ xd_setparam(CMD_XBSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,geometry_table[n][2],geometry_table[n][3],0x0B); xd_recalibrate(drive);}/* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */static void __init xd_override_init_drive (u_char drive){ u_short min[] = { 0,0,0 },max[] = { 16,1024,64 },test[] = { 0,0,0 }; u_char cmdblk[6],i; if (xd_geo[3*drive]) xd_manual_geo_set(drive); else { for (i = 0; i < 3; i++) { while (min[i] != max[i] - 1) { test[i] = (min[i] + max[i]) / 2; xd_build(cmdblk,CMD_SEEK,drive,(u_char) test[0],(u_short) test[1],(u_char) test[2],0,0); if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2)) min[i] = test[i]; else max[i] = test[i]; } test[i] = min[i]; } xd_info[drive].heads = (u_char) min[0] + 1; xd_info[drive].cylinders = (u_short) min[1] + 1; xd_info[drive].sectors = (u_char) min[2] + 1; } xd_info[drive].control = 0;}/* xd_setup: initialise controler from command line parameters */void __init do_xd_setup (int *integers){ switch (integers[0]) { case 4: if (integers[4] < 0) nodma = 1; else if (integers[4] < 8) xd_dma = integers[4]; case 3: if ((integers[3] > 0) && (integers[3] <= 0x3FC)) xd_iobase = integers[3]; case 2: if ((integers[2] > 0) && (integers[2] < 16)) xd_irq = integers[2]; case 1: xd_override = 1; if ((integers[1] >= 0) && (integers[1] < (sizeof(xd_sigs) / sizeof(xd_sigs[0])))) xd_type = integers[1]; case 0: break; default:printk("xd: too many parameters for xd\n"); } xd_maxsectors = 0x01;}/* xd_setparam: set the drive characteristics */static void __init xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc){ u_char cmdblk[14]; xd_build(cmdblk,command,drive,0,0,0,0,0); cmdblk[6] = (u_char) (cylinders >> 8) & 0x03; cmdblk[7] = (u_char) (cylinders & 0xFF); cmdblk[8] = heads & 0x1F; cmdblk[9] = (u_char) (rwrite >> 8) & 0x03; cmdblk[10] = (u_char) (rwrite & 0xFF); cmdblk[11] = (u_char) (wprecomp >> 8) & 0x03; cmdblk[12] = (u_char) (wprecomp & 0xFF); cmdblk[13] = ecc; /* Some controllers require geometry info as data, not command */ if (xd_command(cmdblk,PIO_MODE,0,&cmdblk[6],0,XD_TIMEOUT * 2)) printk("xd: error setting characteristics for xd%c\n", 'a'+drive);}#ifdef MODULEstatic int xd[5] = { -1,-1,-1,-1, };MODULE_PARM(xd, "1-4i");MODULE_PARM(xd_geo, "3-6i");MODULE_PARM(nodma, "i");static void xd_done (void){ struct gendisk ** gdp; blksize_size[MAJOR_NR] = NULL; blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_size[MAJOR_NR] = NULL; hardsect_size[MAJOR_NR] = NULL; read_ahead[MAJOR_NR] = 0; for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) if (*gdp == &xd_gendisk) break; if (*gdp) *gdp = (*gdp)->next; release_region(xd_iobase,4);}int init_module(void){ int i,count = 0; int error; for (i = 4; i > 0; i--) if(((xd[i] = xd[i-1]) >= 0) && !count) count = i; if((xd[0] = count)) do_xd_setup(xd); error = xd_init(); if (error) return error; printk(KERN_INFO "XD: Loaded as a module.\n"); if (!xd_drives) { /* no drives detected - unload module */ devfs_unregister_blkdev(MAJOR_NR, "xd"); xd_done(); return (-1); } return 0;}void cleanup_module(void){ int partition,dev,start; devfs_unregister_blkdev(MAJOR_NR, "xd"); for (dev = 0; dev < xd_drives; dev++) { start = dev << xd_gendisk.minor_shift; for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) { int minor = (start | partition); kdev_t devp = MKDEV(MAJOR_NR, minor); start = dev << xd_gendisk.minor_shift; sync_dev(devp); invalidate_buffers(devp); } } xd_done(); devfs_unregister (devfs_handle); if (xd_drives) { free_irq(xd_irq, NULL); free_dma(xd_dma); if (xd_dma_buffer) xd_dma_mem_free((unsigned long)xd_dma_buffer, xd_maxsectors * 0x200); }}#elsestatic int __init xd_setup (char *str){ int ints[5]; get_options (str, ARRAY_SIZE (ints), ints); do_xd_setup (ints); return 1;}/* xd_manual_geo_init: initialise drive geometry from command line parameters (used only for WD drives) */static int __init xd_manual_geo_init (char *str){ int i, integers[1 + 3*XD_MAXDRIVES]; get_options (str, ARRAY_SIZE (integers), integers); if (integers[0]%3 != 0) { printk("xd: incorrect number of parameters for xd_geo\n"); return 1; } for (i = 0; (i < integers[0]) && (i < 3*XD_MAXDRIVES); i++) xd_geo[i] = integers[i+1]; return 1;}__setup ("xd=", xd_setup);__setup ("xd_geo=", xd_manual_geo_init);#endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -