I am submitting a patch to kernel/sys.c that walks through all IDE drives (#ifdef CONFIG_BLK_DEV_IDE, of course), and issues a "sleep" command (as code in hdparam) to each one of them right before the kernel halts. Here goes the diff:
--- sys.c.ORIG Thu May 24 00:56:50 2001 +++ sys.c Thu May 24 01:40:31 2001 @@ -15,6 +15,11 @@ #include <asm/uaccess.h> #include <asm/io.h> +#ifdef CONFIG_BLK_DEV_IDE +#include "../drivers/block/ide.h" +#endif + + /* * this indicates whether you can reboot with ctrl-alt-del: the default is yes */ @@ -146,6 +151,45 @@ /* + * Puts IDE disks in sleep mode + */ +void disks_sleep(void) { +#ifdef CONFIG_BLK_DEV_IDE +#define WIN_SLEEPNOW1 0xE6 +#define WIN_SLEEPNOW2 0x99 + int i, d, ret; + unsigned char args[4]; + ide_drive_t *drv; + + for ( i=0 ; i<MAX_HWIFS ; i++ ) { + if ( !ide_hwifs[i].present ) + continue; + /*printk(KERN_DEBUG "HD iface %s\n", ide_hwifs[i].name);*/ + for ( d=0 ; d<MAX_DRIVES ; d++ ) { + if ( !ide_hwifs[i].drives[d].present ) + continue; + /*printk(KERN_DEBUG " - drive %s\n", +ide_hwifs[i].drives[d].name);*/ + drv = &ide_hwifs[i].drives[d]; + args[0] = WIN_SLEEPNOW1; + args[1] = args[2] = args[3] = 0; + ret = ide_wait_cmd(drv, args[0], args[1], args[2], args[3], +args); + if (ret) { + args[0] = WIN_SLEEPNOW2; + args[1] = args[2] = args[3] = 0; + ret = ide_wait_cmd(drv, args[0], args[1], args[2], +args[3], args); + if (ret) + printk(KERN_NOTICE "Putting %s to sleep +failed.\n", drv->name); + else + printk(KERN_NOTICE "Putting %s to sleep at +second attempt.\n", drv->name); + } else + printk(KERN_NOTICE "Putting %s to sleep.\n", +drv->name); + } + } +#endif +} + + +/* * Reboot system call: for obvious reasons only root may call it, * and even root needs to set up some magic numbers in the registers * so that some mistake won't make this reboot the whole machine. @@ -186,6 +230,7 @@ case LINUX_REBOOT_CMD_HALT: notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL); printk(KERN_EMERG "System halted.\n"); + disks_sleep(); machine_halt(); do_exit(0); break; @@ -193,6 +238,7 @@ case LINUX_REBOOT_CMD_POWER_OFF: notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL); printk(KERN_EMERG "Power down.\n"); + disks_sleep(); machine_power_off(); do_exit(0); break;
Please comment! Cheers, -- *** Rodrigo Martins de Matos Ventura <[EMAIL PROTECTED]> *** Web page: http://www.isr.ist.utl.pt/~yoda *** Teaching Assistant and PhD Student at ISR: *** Instituto de Sistemas e Robotica, Polo de Lisboa *** Instituto Superior Tecnico, Lisboa, PORTUGAL *** PGP fingerprint = 0119 AD13 9EEE 264A 3F10 31D3 89B3 C6C4 60C6 4585