home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2007 January, February, March & April
/
Chip-Cover-CD-2007-02.iso
/
boot
/
i386
/
root
/
usr
/
share
/
YaST2
/
modules
/
Idedma.ycp
< prev
next >
Wrap
Text File
|
2006-11-29
|
17KB
|
657 lines
/**
* File:
* modules/Idedma.ycp
*
* Package:
* Configuration of IDE DMA mode
*
* Summary:
* Data for configuration of IDE DMA mode, input and output functions.
*
* Authors:
* Ladislav Slezak <lslezak@suse.cz>
*
* $Id: Idedma.ycp 30771 2006-05-09 14:43:39Z lslezak $
*
* Representation of the configuration of IDE DMA mode.
* Input and output routines.
*
*/
{
// Set the name of the module
module "Idedma";
import "Report";
import "Service";
include "hwinfo/classnames.ycp";
textdomain "tune";
// Settings: Define all variables needed for configuration of IDE DMA
/**
* List of all IDE devices with descriptions and DMA settings
*/
list<map<string,any> > ide_devices = [];
/**
* Full path to hdparm binary
*/
string hdparm_bin = "/sbin/hdparm";
/**
* Full path to udev script which sets the DMA mode
*/
string udev_script = "/lib/udev/idedma.sh";
/**
* String with DMA on status text
* (For translators: translation can be long - text is used in the table
* in column "Required DMA mode" and "Current DMA mode")
*/
global string dma_on_string = _("On");
/**
* String with DMA off status text
* (For translators: translation can be long - text is used in the table
* in column "Required DMA mode" and "Current DMA mode")
*/
global string dma_off_string = _("Off");
/**
* String with no change of DMA status text
* (For translators: translation can be long - text is used in the table
* in column "Required DMA mode" and "Current DMA mode")
*/
global string dma_default_string = _("No change");
global map mode_names = $[
// DMA status is unknown
"" : _("Unknown"),
// do not change DMA setting
"nochange" : dma_default_string,
// DMA is enabled, but mode is unknown
"on" : dma_on_string,
// DMA is disabled
"off" : dma_off_string,
"sdma0" : "SW DMA/2.1",
"sdma1" : "SW DMA/4.2",
"sdma2" : "SW DMA/8.3",
"mdma0" : "DMA/4.2",
"mdma1" : "DMA/13.3",
"mdma2" : "DMA/16",
"udmaS" : "UltraDMA/13",
"udma0" : "UltraDMA/16",
"udma1" : "UltraDMA/22",
"udma2" : "UltraDMA/33",
"udma3" : "UltraDMA/44",
"udma4" : "UltraDMA/66",
"udma5" : "UltraDMA/100",
"udma6" : "UltraDMA/133"
];
/**
* Return actual DMA status of IDE device
* @param device Identification of ide device, e.g. "/dev/hdc"
* @return string true if DMA is on, false if DMA is off or nil on error
*/
global define string get_device_dma_status(string device) ``{
string result = "";
if (device != nil && device != "")
{
// run hdparm to get DMA status
map out = (map) SCR::Execute(.target.bash_output, hdparm_bin + " -d " + device);
if (out["exit"]:-1 == 0)
{
list<string> output = splitstring(out["stdout"]:"", "\n");
y2debug("hdparm output: %1", output);
// search for status string in output
foreach(string l, output, ``{
if (l == " using_dma = 1 (on)")
{
result = "on";
}
if (l == " using_dma = 0 (off)")
{
result = "off";
}
}
);
}
}
return result;
}
/**
* Get DMA information status for device
* @param device device name (e.g. "/dev/hdc")
* @return string DMA information from hdparm ("mdma2 udma0 udma1 *udma2")
*/
define string get_dma_info(string device) ``{
string result = "";
if (device != nil && device != "")
{
// DMA mode is enabled, get DMA mode number
map out = (map) SCR::Execute(.target.bash_output, hdparm_bin + " -I " + device);
if (out["exit"]:-1 == 0)
{
list<string> output = splitstring(out["stdout"]:"", "\n");
foreach(string line, output, ``{
string dmaline = (regexpsub(line, "^[ \t]*DMA:[ \t]*(.*)$", "\\1"));
if (dmaline != nil)
{
y2debug("dmaline: %1", dmaline);
result = (result == "") ? dmaline : (result + " " + dmaline);
}
}
);
}
}
y2debug("device: %1 DMA modes: %2", device, result);
return result;
}
/**
* Parse DMA info string from hdparm output - return current DMA mode (has mark '*')
* @param dma_info DMA support string (e.g. "mdma2 udma0 udma1 *udma2")
* @return string current DMA mode or "" if unknown
*/
define string get_current_dma_mode(string dma_info) ``{
string result = "";
if (dma_info != nil && dma_info != "")
{
list<string> modes = splitstring(dma_info, " ");
foreach(string mode, modes, ``{
string current = regexpsub(mode, "^\\*(.*)", "\\1");
if (current != nil)
{
result = current;
}
}
);
}
return result;
}
/**
* Parse DMA info string from hdparm output - return list of supported DMA modes
* @param dma_info DMA support string (e.g. "mdma2 udma0 udma1 *udma2")
* @return list<string> list of supported DMA modes
*/
define list<string> get_supported_dma_modes(string dma_info) ``{
list<string> result = [];
if (dma_info != nil && dma_info != "")
{
list<string> modes = splitstring(dma_info, " ");
foreach(string mode, modes, ``{
if (size(mode) > 0)
{
string current = regexpsub(mode, "^\\*(.*)", "\\1");
// add mode or current mode (filter out * mark)
result = add(result, (current != nil) ? current : mode);
}
}
);
}
else
{
// DMA info line is empty - no information is available
// offer all possible values
result = [ "mdma2", "udma0", "udma2", "udma4", "udma5", "udma6"];
}
return result;
}
/**
* Read all DMA settings from the SCR
* @return boolean true on success
*/
global define boolean Read() ``{
ide_devices = [];
// read information about all IDE devices
list<map<string,any> > devices = (list<map<string, any> >) SCR::Read(.probe.ide);
// remove SATA devices (/dev/sd*)
devices = filter(map<string,any> dn, devices, {
string d = dn["dev_name"]:"";
return regexpmatch(d, "^/dev/hd");
}
);
// read SCSI devices
list<map<string,any> > scsi_devices = (list<map<string, any> >) SCR::Read(.probe.scsi);
if (size(scsi_devices) > 0)
{
// leave only devices with IDE-SCSI emulation
scsi_devices = filter(map<string,any> dev, scsi_devices, ``(dev["driver"]:nil == "ide-scsi"));
}
// add ide-scsi devices to ide devices
if (size(scsi_devices) > 0)
{
devices = (list<map<string,any> >) merge(devices, scsi_devices);
}
y2milestone("Detected ide-scsi devices: %1", scsi_devices);
// read setting from sysconfig
string devices_setting_str = (string) SCR::Read(.sysconfig.ide.DEVICES_FORCE_IDE_DMA);
y2debug("Read configuration: %1", devices_setting_str);
if (devices_setting_str == nil)
{
devices_setting_str = "";
}
// split string to list of devices
list<string> device_settings = splitstring(devices_setting_str, " ");
// create map of settings <device>:<DMA_setting>
map device_setting_map = $[];
foreach(string setting, device_settings, ``{
string dev = regexpsub(setting, "^(.*):(.*)", "\\1");
string mode = regexpsub(setting, "^(.*):(.*)", "\\2");
if (size(dev) > 0 && size(mode) > 0)
{
device_setting_map = add(device_setting_map, dev, mode);
}
}
);
y2milestone("Read config: %1", device_setting_map);
// for each detected IDE device build internal
foreach(map<string, any> dev, devices, ``{
// device model name is unknown
string device = (string) (dev["device"]:_("Unknown device"));
string dev_name = (string) (dev["dev_name"]:nil);
string scsi_name = nil;
if (dev["driver"]:nil == "ide-scsi")
{
// this is ide-scsi device
// set device name to IDE name
dev_name = (string) (dev["dev_name2"]:nil);
scsi_name = (string) (dev["dev_name"]:nil);
}
if (dev_name != nil)
{
integer subclass_id = (integer) (dev["sub_class_id"]:nil);
integer class_id = (integer) (dev["class_id"]:nil);
string dma_setting = device_setting_map[dev_name]:"nochange";
// get textual information about device type (disk, CD-ROM, tape, ...) from identification number - device type was not found
string subclass_id_string = (string) eval(ClassNames[class_id, subclass_id]: _("Unknown device type"));
// get current DMA setting
string current_dma = get_device_dma_status(dev_name);
string dma_info = get_dma_info(dev_name);
y2milestone("dma_info: %1", dma_info);
string current_dma_string = get_current_dma_mode(dma_info);
if (current_dma == "on" && size(current_dma_string) > 0)
{
current_dma = current_dma_string;
}
list<string> dma_modes = get_supported_dma_modes(dma_info);
map<string,any> dev_map = $["device" : device, "dev_name" : dev_name, "dma_setting" : dma_setting, "device_type" : subclass_id_string, "current_dma" : current_dma, "dma_modes" : dma_modes];
if (scsi_name != nil)
{
// add scsi name if device is ide-scsi
dev_map["scsi_name"] = scsi_name;
}
ide_devices = (list<map<string,any> >) add(ide_devices, dev_map);
}
}
);
y2milestone("Detected IDE devices: %1", ide_devices);
return true;
}
/**
* Return information about all IDE devices
* @return list List of maps with information about all IDE devices
*/
global define list<map> get_ide_devices() ``{
return ide_devices;
}
/**
* Get list of supported DMA modes for selected device
* @param device device name ("/dev/hda")
* @return list supported DMA modes (["mdma2", "udma0", "udma1", "udma2"])
*/
global define list supported_dma_modes(string device) ``{
list result = [];
if (size(device) > 0)
{
foreach(map info, ide_devices, ``{
if (info["dev_name"]:"" == device)
{
result = info["dma_modes"]:[];
}
}
);
}
return result;
}
/**
* Get selected DMA mode, which will be saved and set in Write
* @param device device name ("/dev/hda")
* @return string selected DMA mode ("on", "off", "nochange", or mode supported by hdparm - "udma5",...)
*/
global define string selected_mode(string device) ``{
string mode = "";
if (size(device) > 0)
{
foreach(map info, ide_devices, ``{
if (info["dev_name"]:"" == device)
{
mode = info["dma_setting"]:"";
}
}
);
}
return mode;
}
/**
* Set DMA of device
* @param device Identification of IDE device, e.g. "/dev/hda"
* @param dma_setting DMA mode (e.g. "mdma2", "udma5", "off",...)
* @return boolean true on success
*/
global define boolean set_dma(string device, string dma_setting) ``{
if (device == nil || device == "" || dma_setting == nil || dma_setting == "")
{
return false;
}
// check if mode name in known
if (!haskey(mode_names, dma_setting))
{
return false;
}
// store required DMA status
ide_devices = maplist(map<string,any> d, ide_devices, ``{
if (d["dev_name"]:nil == device)
{
d = add(d, "dma_setting", dma_setting);
}
return d;
}
);
return true;
}
/**
* Update the SCR according to DMA settings
* @return boolean true on success
*/
global define boolean Write() ``{
boolean ret = true;
// create strings with device indentifications
// e.g. new_dma_setting = "/dev/hda:udma5 /dev/hdc:off";
string new_dma_setting = "";
boolean first = true;
// is boot.idedma init script needed?
// avoid calling hdparm if configuration wasn't changed
boolean initscript_needed = false;
// is sync call needed?
// call sync before DMA is turned on, usefull when machine
// hangs just after enabling DMA
boolean sync_needed = false;
map<string,string> changeDMA = $[];
y2milestone("ide_devices: %1", ide_devices);
foreach(map<string, any> d, ide_devices, ``{
string d_name = (string) (d["dev_name"]:nil);
if (d_name != nil)
{
string dma_setting = (string) (d["dma_setting"]:"nochange");
string dma_current_setting = (string) (d["current_dma"]:"nochange");
string dma_required_setting = dma_setting;
if (dma_setting != "nochange")
{
y2debug("d_name: %1 dma_setting: %2", d_name, dma_setting);
dma_setting = d_name + ":" + dma_setting;
if (first == true)
{
new_dma_setting = dma_setting;
first = false;
}
else
{
new_dma_setting = new_dma_setting + " " + dma_setting;
}
y2debug("dma_setting: %1, dma_current_setting: %2", dma_setting, dma_current_setting);
// use boot.idedma only if current DMA mode and required DMA mode differ
if (dma_required_setting != dma_current_setting &&
// don't distinguish between "on" and exact DMA mode
// (required is "on", current is not "off" nor "nochange" (it is e.g. "udma2"))
!(dma_required_setting == "on" && dma_current_setting != "off" && dma_current_setting != "nochange")
)
{
initscript_needed = true;
if (dma_current_setting == "off" && dma_required_setting != "off" && dma_required_setting != "nochange")
{
sync_needed = true;
}
// remember the new setting
changeDMA[d_name] = dma_required_setting;
}
}
}
}
);
y2milestone("new_dma_setting: %1", new_dma_setting);
// write device strings to sysconfig
if (SCR::Write(.sysconfig.ide.DEVICES_FORCE_IDE_DMA, new_dma_setting) == false)
{
// error message - %1 is file name
Report::Error(sformat(_("Unable to write settings to '%1'."), "/etc/sysconfig/ide"));
return false;
}
// flush changes
SCR::Write(.sysconfig.ide, nil);
// flush disc cache before enabling DMA
if (sync_needed == true)
{
y2milestone("Flushing disc cache before enabling DMA...");
integer exit = (integer) SCR::Execute(.target.bash, "/bin/sync");
if (exit != 0)
{
y2warning("Warning: sync failed! (status = %1)", exit);
}
}
// activate settings
if (initscript_needed == true)
{
foreach(string dev, string mode, changeDMA, {
y2milestone("Changing DMA mode: device=%1 mode=%2", dev, mode);
if (mode != "nochange")
{
string command = udev_script + " " + dev;
y2milestone("Starting '%1'", command);
integer result = (integer) SCR::Execute(.target.bash, command);
if (result != 0)
{
// error message
// %1 is string "on", "off" or DMA string mode e.g. "udma5", "mdma2", ...
// %2 is device node (e.g. /dev/hdc)
Report::Error(sformat(_("An error occurred while activating the changes.\nCannot set required mode '%1' for device %2."), mode, dev));
ret = false;
}
}
}
);
}
return ret;
}
/**
* Set module data
* @param settings set data from YCP
* @return void
*/
global define void Set (list<map<string,any> > settings) ``{
ide_devices = settings;
return;
}
/**
* Get all IDE DMA settings from the first parameter
* (For use by autoinstallation.)
* @param settings The YCP structure to be imported.
* @return boolean True
*/
global define boolean Import (list<map<string,any> > settings) ``{
if (size(settings) == 0)
{
return false;
}
Set(settings);
return true;
}
/**
* Dump the IDE DMA settings to a single map
* (For use by autoinstallation.)
* @return list Dumped settings (later acceptable by Import ())
*/
global define list Export () ``{
return ide_devices ;
}
/**
* Set system configuration without reading values from
* system - for testing and screenshot mode
*/
global define void set_test_data() ``{
ide_devices = [ $["current_dma":"udma2", "dev_name":"/dev/hda",
"device":"IBM-DJNA-351520", "device_type":"Disk", "dma_setting":"udma2"],
$["current_dma":"off", "dev_name":"/dev/hdc", "device":"CD-532E-B",
"device_type":"CD-ROM", "dma_on":"nochange"]
];
}
/**
* Create rich text description of the current configuration
* @param all when true all IDE devices are contained in the summary text
* (even unconfigured devices with default DMA mode)
* @param richtext select rich/plain text output
* @return string summary text
*/
global define string Summary(boolean all, boolean richtext) ``{
// summary text - header
string summary = (all == true) ? ((richtext) ? "<P><B>":"") + _("All IDE Devices:") + ((richtext) ? "</B></P>":"\n") : ((richtext) ? "<P><B>":"") + _("Configured Devices:") + ((richtext) ? "</B></P>":"\n");
string devices = "";
boolean found = false;
if (size(ide_devices) > 0)
{
foreach(map<string, any> dev, ide_devices, ``{
string dmasetting = (string) (dev["dma_setting"]:nil);
string devname = (string) (dev["dev_name"]:nil);
if (devname != nil && dmasetting != nil && (all == true || dmasetting != "nochange"))
{
// summary text - unknown DMA mode is selected
devices = devices + ((richtext) ? "<LI><B>":"") + devname + ":" + ((richtext) ? "</B>":"") + " " + sformat("%1 (%2)", dmasetting, mode_names[dmasetting]:_("Unknown mode")) + ((richtext) ? "</LI>":"\n");
found = true;
}
}
);
}
// is any device configured?
if (found == false)
{
// summary text - none device is configured
devices = ((richtext) ? "<LI>":"") + _("No device") + ((richtext) ? "</LI>":"\n");
}
return summary + ((richtext) ? "<UL>":"") + devices + ((richtext) ? "</UL>":"");
}
}