[PATCH] modularne IDE w kernelu (fwd)
Tomasz Kłoczko
kloczek w rudy.mif.pg.gda.pl
Wto, 17 Paź 2000, 20:07:21 CEST
mały fwd który sie odbił z racji tego, że Andrzej nie jest zapisany.
---------- Forwarded message ----------
Date: Tue, 17 Oct 2000 16:15:08 +0200 (CEST)
From: Andrzej Krzysztofowicz <ankry w green.mif.pg.gda.pl>
To: pld-list w pld.org.pl
Cc: kloczek w rudy.mif.pg.gda.pl
Subject: [PATCH] modularne IDE w kernelu
Witam wszystkich.
Zalaczam wstepnie przetestowana, ale wciaz niedokonczona wersje pacza do
kernela 2.2.17+ide(hedrick) umozliwiajaca w miare stabilna prace z
modularnym IDE. Poprzedni moj pacz (wyslany na liste przez T.Kloczko)
w sposob oczywisty nie dzialal, wiec troche sie dziwie, ze nikt tego nie
zauwazyl... (byl pisany "na sucho"; nie mialem mozliwosci go przetestowac).
Obecna wersja usuwa nastepujace problemy:
1. rozpoznawanie logicznej "geometrii" przez modul IDE
2. oops przy nieprawidlowej kolejnosci ladowania modulow i wlaczonym DMA
(testowane na alim15xx+PCIDMA:
insmod ide-mod;insmod ide-disk;insmod ide-probe-mod;rmmod ide-probe-mod
rmmod ide-disk;insmod ide-probe-mod;insmod ide-disk ---> Oops )
3. wrazliwosc inicjalizacji na kolejnosc ladowania modulow (probe, dirver)
4. nierejestrowanie niektorych wpisow w /proc prze niewlasciwej kolejnosci
j.w.
5. zablokowana mozliwosc reskanowania kanalow IDE. Pewnie niektorych to
zmartwi, ale nie powinno. Patrz komentarz w zrodlach. Ponadto gryzie sie
z modularnym ide. Inicjalizacje subsystemu IDE w kernelu nalezaloby
wlasciwie napisac od nowa...
Problemy, ktore nadal wystepuja (a o ktorych wiem):
- przeladowanie ide-probe przy zaladowanym ide-disk nie inicjalizuje
poprawnie DMA. (zwykle pomaga hdparm -d0/hdparm -d1, aczkolwiek zdaza sie,
ze dysk ogluchnie totalnie). Problemy moga nie wystepowac przy niektorych
chipsetach (testowalem na ALi)
- balagan z #ifdef'ami (brak, niewlasciwe) w drajwerach chipsetow powodujacy
niekompilowanie sie niektorych konfiguracji (raczej nietypowych)
- nie do konca rozseparowane drajwery ide i hd (nie wszystko dziala jak
powinno). Ale to moze byc istotne wylacznie dla posiadaczy starego sprzetu
i malej ilosci RAM.
- (?) niedokonczona modularyzacja drajwerow do czipsetow...
Ewentualne komentarze prosze na adres osobisty, gdyz nie jestem zapisany na
liste.
Pozdrawiam
Andrzej
************************************************************************
diff -uNr linux-PLD/drivers/block/Makefile linux/drivers/block/Makefile
--- linux-PLD/drivers/block/Makefile Sat Oct 7 13:18:38 2000
+++ linux/drivers/block/Makefile Sun Oct 8 15:19:21 2000
@@ -20,10 +20,10 @@
L_TARGET := block.a
-L_OBJS := genhd.o ide-geometry.o
+L_OBJS :=
M_OBJS :=
MOD_LIST_NAME := BLOCK_MODULES
-LX_OBJS := ll_rw_blk.o
+LX_OBJS := ll_rw_blk.o genhd.o
MX_OBJS :=
ifeq ($(CONFIG_MAC_FLOPPY),y)
@@ -259,11 +259,11 @@
###Collect
ifeq ($(CONFIG_BLK_DEV_IDE),y)
- LX_OBJS += ide.o ide-features.o
+ LX_OBJS += ide.o ide-features.o ide-geometry.o
L_OBJS += ide-probe.o $(IDE_OBJS)
else
ifeq ($(CONFIG_BLK_DEV_IDE),m)
- MIX_OBJS += ide.o ide-features.o $(IDE_OBJS)
+ MIX_OBJS += ide.o ide-features.o ide-geometry.o $(IDE_OBJS)
M_OBJS += ide-mod.o ide-probe-mod.o
endif
endif
@@ -408,8 +408,8 @@
include $(TOPDIR)/Rules.make
-ide-mod.o: ide.o ide-features.o $(IDE_OBJS)
- $(LD) $(LD_RFLAG) -r -o $@ ide.o ide-features.o $(IDE_OBJS)
+ide-mod.o: ide.o ide-features.o ide-geometry.o $(IDE_OBJS)
+ $(LD) $(LD_RFLAG) -r -o $@ ide.o ide-features.o ide-geometry.o $(IDE_OBJS)
-ide-probe-mod.o: ide-probe.o ide-geometry.o
- $(LD) $(LD_RFLAG) -r -o $@ ide-probe.o ide-geometry.o
+ide-probe-mod.o: ide-probe.o
+ $(LD) $(LD_RFLAG) -r -o $@ ide-probe.o
diff -uNr linux-PLD/drivers/block/genhd.c linux/drivers/block/genhd.c
--- linux-PLD/drivers/block/genhd.c Sat Oct 7 13:18:38 2000
+++ linux/drivers/block/genhd.c Sun Oct 8 16:49:00 2000
@@ -29,6 +29,7 @@
#include <linux/blk.h>
#include <linux/init.h>
#include <linux/raid/md.h>
+#include <linux/ide-geometry.h>
#include <asm/system.h>
#include <asm/byteorder.h>
@@ -72,6 +73,11 @@
extern void note_bootable_part(kdev_t dev, int part);
#endif
+/*
+ * This is a handler for ide_xlate_1024()
+ */
+idexlatefunc_t * ide_xlate_handler = NULL;
+
static char *raid_name (struct gendisk *hd, int minor, int major_base,
char *buf)
{
@@ -510,11 +516,9 @@
kdev_t bsd_kdev = 0;
int bsd_maxpart = BSD_MAXPARTITIONS;
#endif
-#ifdef CONFIG_BLK_DEV_IDE
int tested_for_xlate = 0;
read_mbr:
-#endif
if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
printk(" unable to read partition table\n");
return -1;
@@ -533,9 +537,7 @@
/* of the drive (below), so ensure that */
/* nobody else tries to re-use this data. */
bh->b_state = 0;
-#ifdef CONFIG_BLK_DEV_IDE
check_table:
-#endif
/* Use bforget(), because we have potentially changed the disk geometry */
if (*(unsigned short *) (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
bforget(bh); /* brelse(bh); */
@@ -543,12 +545,10 @@
}
p = (struct partition *) (0x1be + data);
-#ifdef CONFIG_BLK_DEV_IDE
- if (!tested_for_xlate++) { /* Do this only once per disk */
+ if (ide_xlate_handler && !tested_for_xlate++) { /* Do this only once per disk */
/*
* Look for various forms of IDE disk geometry translation
*/
- extern int ide_xlate_1024(kdev_t, int, int, const char *);
unsigned int sig = le16_to_cpu(*(unsigned short *)(data + 2));
int heads = 0;
@@ -572,7 +572,7 @@
/*
* Accesses to sector 0 must go to sector 1 instead.
*/
- if (ide_xlate_1024(dev, -1, heads, " [EZD]")) {
+ if (ide_xlate_handler(dev, -1, heads, " [EZD]")) {
data += 512;
goto check_table;
}
@@ -582,7 +582,7 @@
* Everything on the disk is offset by 63 sectors,
* including a "new" MBR with its own partition table.
*/
- if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]")) {
+ if (ide_xlate_handler(dev, 1, heads, " [DM6:DDO]")) {
bforget(bh); /* brelse(bh); */
goto read_mbr; /* start over with new MBR */
}
@@ -595,18 +595,17 @@
(data[sig+2] & 1)) {
#endif
/* DM6 signature in MBR, courtesy of OnTrack */
- (void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]");
+ (void) ide_xlate_handler(dev, 0, heads, " [DM6:MBR]");
} else if (SYS_IND(p) == DM6_AUX1PARTITION ||
SYS_IND(p) == DM6_AUX3PARTITION) {
/*
* DM6 on other than the first (boot) drive
*/
- (void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]");
+ (void) ide_xlate_handler(dev, 0, heads, " [DM6:AUX]");
} else {
- (void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
+ (void) ide_xlate_handler(dev, 2, heads, " [PTBL]");
}
}
-#endif /* CONFIG_BLK_DEV_IDE */
/*
* The Linux code now honours the rules the MO people set and
@@ -1716,3 +1715,5 @@
return len;
}
#endif
+
+EXPORT_SYMBOL(ide_xlate_handler);
diff -uNr linux-PLD/drivers/block/ide-dma.c linux/drivers/block/ide-dma.c
--- linux-PLD/drivers/block/ide-dma.c Sat Oct 7 13:18:38 2000
+++ linux/drivers/block/ide-dma.c Sun Oct 8 22:33:24 2000
@@ -100,7 +100,7 @@
char * id_firmware;
};
-struct drive_list_entry drive_whitelist [] = {
+static struct drive_list_entry drive_whitelist [] = {
{ "Micropolis 2112A" , "ALL" },
{ "CONNER CTMA 4000" , "ALL" },
@@ -109,7 +109,7 @@
{ 0 , 0 }
};
-struct drive_list_entry drive_blacklist [] = {
+static struct drive_list_entry drive_blacklist [] = {
{ "WDC AC11000H" , "ALL" },
{ "WDC AC22100H" , "ALL" },
@@ -307,34 +307,34 @@
}
#if 0
-+static int ide_raw_build_sglist (ide_hwif_t *hwif, struct request *rq)
-+{
-+ struct scatterlist *sg = hwif->sg_table;
-+ int nents = 0;
-+ ide_task_t *args = rq->special;
-+ unsigned char *virt_addr = rq->buffer;
-+ int sector_count = rq->nr_sectors;
-+
-+ if (args->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA)
-+ hwif->sg_dma_direction = PCI_DMA_TODEVICE;
-+ else
-+ hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
-+
-+ if (sector_count > 128) {
-+ memset(&sg[nents], 0, sizeof(*sg));
-+ sg[nents].address = virt_addr;
-+ sg[nents].length = 128 * SECTOR_SIZE;
-+ nents++;
-+ virt_addr = virt_addr + (128 * SECTOR_SIZE);
-+ sector_count -= 128;
-+ }
-+ memset(&sg[nents], 0, sizeof(*sg));
-+ sg[nents].address = virt_addr;
-+ sg[nents].length = sector_count * SECTOR_SIZE;
-+ nents++;
-+
-+ return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
-+}
+static int ide_raw_build_sglist (ide_hwif_t *hwif, struct request *rq)
+{
+ struct scatterlist *sg = hwif->sg_table;
+ int nents = 0;
+ ide_task_t *args = rq->special;
+ unsigned char *virt_addr = rq->buffer;
+ int sector_count = rq->nr_sectors;
+
+ if (args->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA)
+ hwif->sg_dma_direction = PCI_DMA_TODEVICE;
+ else
+ hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
+
+ if (sector_count > 128) {
+ memset(&sg[nents], 0, sizeof(*sg));
+ sg[nents].address = virt_addr;
+ sg[nents].length = 128 * SECTOR_SIZE;
+ nents++;
+ virt_addr = virt_addr + (128 * SECTOR_SIZE);
+ sector_count -= 128;
+ }
+ memset(&sg[nents], 0, sizeof(*sg));
+ sg[nents].address = virt_addr;
+ sg[nents].length = sector_count * SECTOR_SIZE;
+ nents++;
+
+ return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
+}
#endif
@@ -381,7 +381,7 @@
return 0;
}
-int report_drive_dmaing (ide_drive_t *drive)
+static int report_drive_dmaing (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
diff -uNr linux-PLD/drivers/block/ide-geometry.c linux/drivers/block/ide-geometry.c
--- linux-PLD/drivers/block/ide-geometry.c Sat Oct 7 13:18:38 2000
+++ linux/drivers/block/ide-geometry.c Sun Oct 8 15:19:21 2000
@@ -1,85 +1,8 @@
/*
* linux/drivers/ide/ide-geometry.c
*/
-#include <linux/config.h>
#include <linux/ide.h>
-#include <asm/io.h>
-
-/*
- * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc
- * controller that is BIOS compatible with ST-506, and thus showing up in our
- * BIOS table, but not register compatible, and therefore not present in CMOS.
- *
- * Furthermore, we will assume that our ST-506 drives <if any> are the primary
- * drives in the system -- the ones reflected as drive 1 or 2. The first
- * drive is stored in the high nibble of CMOS byte 0x12, the second in the low
- * nibble. This will be either a 4 bit drive type or 0xf indicating use byte
- * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. A non-zero value
- * means we have an AT controller hard disk for that drive.
- *
- * Of course, there is no guarantee that either drive is actually on the
- * "primary" IDE interface, but we don't bother trying to sort that out here.
- * If a drive is not actually on the primary interface, then these parameters
- * will be ignored. This results in the user having to supply the logical
- * drive geometry as a boot parameter for each drive not on the primary i/f.
- */
-/*
- * The only "perfect" way to handle this would be to modify the setup.[cS] code
- * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info
- * for us during initialization. I have the necessary docs -- any takers? -ml
- */
-/*
- * I did this, but it doesnt work - there is no reasonable way to find the
- * correspondence between the BIOS numbering of the disks and the Linux
- * numbering. -aeb
- *
- * The code below is bad. One of the problems is that drives 1 and 2
- * may be SCSI disks (even when IDE disks are present), so that
- * the geometry we read here from BIOS is attributed to the wrong disks.
- * Consequently, also the former "drive->present = 1" below was a mistake.
- *
- * Eventually the entire routine below should be removed.
- */
-void probe_cmos_for_drives (ide_hwif_t *hwif)
-{
-#ifdef __i386__
- extern struct drive_info_struct drive_info;
- byte cmos_disks, *BIOS = (byte *) &drive_info;
- int unit;
-
-#ifdef CONFIG_BLK_DEV_PDC4030
- if (hwif->chipset == ide_pdc4030 && hwif->channel != 0)
- return;
-#endif /* CONFIG_BLK_DEV_PDC4030 */
- outb_p(0x12,0x70); /* specify CMOS address 0x12 */
- cmos_disks = inb_p(0x71); /* read the data from 0x12 */
- /* Extract drive geometry from CMOS+BIOS if not already setup */
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
-
- if ((cmos_disks & (0xf0 >> (unit*4)))
- && !drive->present && !drive->nobios) {
- unsigned short cyl = *(unsigned short *)BIOS;
- unsigned char head = *(BIOS+2);
- unsigned char sect = *(BIOS+14);
- if (cyl > 0 && head > 0 && sect > 0 && sect < 64) {
- drive->cyl = drive->bios_cyl = cyl;
- drive->head = drive->bios_head = head;
- drive->sect = drive->bios_sect = sect;
- drive->ctl = *(BIOS+8);
- } else {
- printk("hd%d: C/H/S=%d/%d/%d from BIOS ignored\n",
- unit, cyl, head, sect);
- }
- }
-
- BIOS += 16;
- }
-#endif
-}
-
-
-#ifdef CONFIG_BLK_DEV_IDE
+#include <linux/ide-geometry.h>
extern ide_drive_t * get_info_ptr(kdev_t);
extern unsigned long current_capacity (ide_drive_t *);
@@ -118,6 +41,7 @@
*c = total / (63 * headp[0]);
}
+
/*
* This routine is called from the partition-table code in pt/msdos.c.
* It has two tasks:
@@ -211,4 +135,3 @@
drive->bios_cyl, drive->bios_head, drive->bios_sect);
return ret;
}
-#endif /* CONFIG_BLK_DEV_IDE */
diff -uNr linux-PLD/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c
--- linux-PLD/drivers/block/ide-probe.c Sat Oct 7 13:18:38 2000
+++ linux/drivers/block/ide-probe.c Mon Oct 16 23:20:54 2000
@@ -431,6 +431,79 @@
return(region_errors);
}
+/*
+ * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc
+ * controller that is BIOS compatible with ST-506, and thus showing up in our
+ * BIOS table, but not register compatible, and therefore not present in CMOS.
+ *
+ * Furthermore, we will assume that our ST-506 drives <if any> are the primary
+ * drives in the system -- the ones reflected as drive 1 or 2. The first
+ * drive is stored in the high nibble of CMOS byte 0x12, the second in the low
+ * nibble. This will be either a 4 bit drive type or 0xf indicating use byte
+ * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. A non-zero value
+ * means we have an AT controller hard disk for that drive.
+ *
+ * Of course, there is no guarantee that either drive is actually on the
+ * "primary" IDE interface, but we don't bother trying to sort that out here.
+ * If a drive is not actually on the primary interface, then these parameters
+ * will be ignored. This results in the user having to supply the logical
+ * drive geometry as a boot parameter for each drive not on the primary i/f.
+ */
+/*
+ * The only "perfect" way to handle this would be to modify the setup.[cS] code
+ * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info
+ * for us during initialization. I have the necessary docs -- any takers? -ml
+ */
+/*
+ * I did this, but it doesnt work - there is no reasonable way to find the
+ * correspondence between the BIOS numbering of the disks and the Linux
+ * numbering. -aeb
+ *
+ * The code below is bad. One of the problems is that drives 1 and 2
+ * may be SCSI disks (even when IDE disks are present), so that
+ * the geometry we read here from BIOS is attributed to the wrong disks.
+ * Consequently, also the former "drive->present = 1" below was a mistake.
+ *
+ * Eventually the entire routine below should be removed.
+ */
+static void probe_cmos_for_drives (ide_hwif_t *hwif)
+{
+#ifdef __i386__
+ extern struct drive_info_struct drive_info;
+ byte cmos_disks, *BIOS = (byte *) &drive_info;
+ int unit;
+
+#ifdef CONFIG_BLK_DEV_PDC4030
+ if (hwif->chipset == ide_pdc4030 && hwif->channel != 0)
+ return;
+#endif /* CONFIG_BLK_DEV_PDC4030 */
+ outb_p(0x12,0x70); /* specify CMOS address 0x12 */
+ cmos_disks = inb_p(0x71); /* read the data from 0x12 */
+ /* Extract drive geometry from CMOS+BIOS if not already setup */
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ ide_drive_t *drive = &hwif->drives[unit];
+
+ if ((cmos_disks & (0xf0 >> (unit*4)))
+ && !drive->present && !drive->nobios) {
+ unsigned short cyl = *(unsigned short *)BIOS;
+ unsigned char head = *(BIOS+2);
+ unsigned char sect = *(BIOS+14);
+ if (cyl > 0 && head > 0 && sect > 0 && sect < 64) {
+ drive->cyl = drive->bios_cyl = cyl;
+ drive->head = drive->bios_head = head;
+ drive->sect = drive->bios_sect = sect;
+ drive->ctl = *(BIOS+8);
+ } else {
+ printk("hd%d: C/H/S=%d/%d/%d from BIOS ignored\n",
+ unit, cyl, head, sect);
+ }
+ }
+
+ BIOS += 16;
+ }
+#endif
+}
+
static void hwif_register (ide_hwif_t *hwif)
{
if ((hwif->io_ports[IDE_DATA_OFFSET] | 7) ==
@@ -477,8 +550,6 @@
if (hwif->noprobe)
return;
if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) {
- extern void probe_cmos_for_drives(ide_hwif_t *);
-
probe_cmos_for_drives (hwif);
}
diff -uNr linux-PLD/drivers/block/ide.c linux/drivers/block/ide.c
--- linux-PLD/drivers/block/ide.c Sat Oct 7 13:18:38 2000
+++ linux/drivers/block/ide.c Mon Oct 16 23:20:55 2000
@@ -139,6 +139,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ide.h>
+#include <linux/ide-geometry.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -2082,11 +2083,13 @@
if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
return -ENXIO;
+#if 0
if (drive->media == ide_disk) {
int minor = (MINOR(inode->i_rdev) & PARTN_MASK);
if (drive->part[minor].nr_sects == 0)
return -ENXIO; /* no such partition */
}
+#endif
MOD_INC_USE_COUNT;
if (drive->driver == NULL)
ide_driver_module();
@@ -2325,6 +2328,7 @@
kfree(gd);
}
old_hwif = *hwif;
+#if 0
init_hwif_data (index); /* restore hwif data to pristine status */
hwif->hwgroup = old_hwif.hwgroup;
hwif->tuneproc = old_hwif.tuneproc;
@@ -2352,6 +2356,7 @@
#endif /* CONFIG_BLK_DEV_IDEPCI */
hwif->straight8 = old_hwif.straight8;
hwif->hwif_data = old_hwif.hwif_data;
+#endif /* 0 */
abort:
restore_flags(flags); /* all CPUs */
}
@@ -3106,6 +3111,10 @@
case HDIO_SCAN_HWIF:
{
+#if 0
+/* It doesn't work with PCI interfaces properly and is useless for ISA
+ interfaces - so I disable it (ankry w green.mif.pg.gda.pl) */
+
int args[3];
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES;
if (copy_from_user(args, (void *)arg, 3 * sizeof(int)))
@@ -3113,6 +3122,9 @@
if (ide_register(args[0], args[1], args[2]) == -1)
return -EIO;
return 0;
+#else
+ return -ENOSYS;
+#endif
}
case HDIO_UNREGISTER_HWIF:
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
@@ -4018,6 +4030,7 @@
* Probe module
*/
EXPORT_SYMBOL(ide_probe);
+EXPORT_SYMBOL(ide_modules);
EXPORT_SYMBOL(drive_is_flashcard);
EXPORT_SYMBOL(ide_timer_expiry);
EXPORT_SYMBOL(ide_intr);
@@ -4118,6 +4131,7 @@
}
init_ide_data ();
+ ide_xlate_handler = &ide_xlate_1024;
initializing = 1;
ide_init_builtin_drivers();
@@ -4163,6 +4177,7 @@
for (index = 0; index < MAX_HWIFS; ++index)
ide_unregister(index);
+ ide_xlate_handler = NULL;
#ifdef CONFIG_PROC_FS
proc_ide_destroy();
#endif
diff -uNr linux-PLD/include/linux/ide-geometry.h linux/include/linux/ide-geometry.h
--- linux-PLD/include/linux/ide-geometry.h Thu Jan 1 01:00:00 1970
+++ linux/include/linux/ide-geometry.h Sun Oct 8 00:53:07 2000
@@ -0,0 +1,4 @@
+
+typedef int (idexlatefunc_t)(kdev_t, int, int, const char *);
+
+extern idexlatefunc_t *ide_xlate_handler;
--
=======================================================================
Andrzej M. Krzysztofowicz ankry w mif.pg.gda.pl
tel. (0-58) 347 14 61
Wydz.Fizyki Technicznej i Matematyki Stosowanej Politechniki Gdanskiej
Więcej informacji o liście dyskusyjnej pld-devel-pl