ata: ahci: Enclosure Management via LED
PATCH 1/1 ata: ahci: Enclosure Management via LED
This patch implements Enclosure Management via the LED protocol. See the AHCI 1.1 spec for details.
---
Here's a new version of the Enclosure management patch I sent a few weeks ago. I tried to incorporate all the feedback, although I'm still checking on whether it's ok to use these capability bits on a 1.0 ahci device. Please let me know if there are additional changes needed.
drivers/ata/ahci.c | 152 ++++++++++++++++++++++++++++++++++++++++++++- drivers/ata/libata-scsi.c | 5 +- include/linux/libata.h | 2 + 3 files changed, 155 insertions(+), 4 deletions(-)
drivers/ata/ahci.c +150 -2
@@ -44,6 +44,7 @@#include <linux/dmi.h> #include <scsi/scsi_host.h> #include <scsi/scsi_cmnd.h> +#include <scsi/scsi_device.h> #include <linux/libata.h> #define DRV_NAME "ahci"
@@ -92,6 +93,8 @@ enum {HOST_IRQ_STAT =0x08 ,/* interrupt status */ HOST_PORTS_IMPL =0x0c ,/* bitmap of implemented ports */ HOST_VERSION =0x10 ,/* AHCI spec. version compliancy */ +HOST_EM_LOC =0x1c ,/* Enclosure Management location */ +HOST_EM_CTL =0x20 ,/* Enclosure Management Control */ /* HOST_CTL bits */ HOST_RESET = (1 << 0), /* reset controller; self-clear */
@@ -99,6 +102,7 @@ enum {HOST_AHCI_EN = (1 <<31 ),/* AHCI enabled */ /* HOST_CAP bits */ +HOST_CAP_EMS = (1 <<6 ),/* Enclosure Management support */ HOST_CAP_SSC = (1 <<14 ),/* Slumber capable */ HOST_CAP_PMP = (1 <<17 ),/* Port Multiplier support */ HOST_CAP_CLO = (1 << 24), /* Command List Override support */
@@ -193,6 +197,10 @@ enum {ATA_FLAG_ACPI_SATA |ATA_FLAG_AN |ATA_FLAG_IPM ,AHCI_LFLAG_COMMON =ATA_LFLAG_SKIP_D2H_BSY , + +/* em_ctl bits */ +EM_CTL_RST = (1 <<9 ),/* Reset */ + EM_CTL_TM = (1 << 8), /* Transmit Message */ }; struct ahci_cmd_hdr {
@@ -216,6 +224,7 @@ struct ahci_host_priv {u32 port_map;/* port map to use */ u32 saved_cap;/* saved initial cap */ u32 saved_port_map;/* saved initial port_map */ +u32 em_loc;/* enclosure management location */ };struct ahci_port_priv {
@@ -231,6 +240,7 @@ struct ahci_port_priv { unsigned int ncq_saw_dmas:1; unsigned int ncq_saw_sdb:1;u32 intr_mask;/* interrupts to enable */ +u16 led_state;/* saved current led state */ };static int ahci_scr_read (struct ata_port *ap,unsigned int sc_reg,u32 *val);
@@ -572,6 +582,11 @@ static struct pci_driver ahci_pci_driver = {#endif }; +static int ahci_em_messages =1 ; +module_param (ahci_em_messages, int,0444 ); +/* add other LED protocol types when they become supported */ +MODULE_PARM_DESC (ahci_em_messages, +"Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED" );static inline int ahci_nr_ports (u32 cap) {
@@ -1082,6 +1097,116 @@ static int ahci_reset_controller(struct ata_host *host)return 0 ; } +/****** LED Enclosure Management routines ********/ +static int ahci_reset_em (struct ata_host *host) +{ +void __iomem *mmio = host->iomap[AHCI_PCI_BAR ]; +u32 em_ctl; + + em_ctl =readl (mmio +HOST_EM_CTL ); +if ((em_ctl &EM_CTL_TM ) || (em_ctl &EM_CTL_RST )) +return -EINVAL ; + +writel (em_ctl |EM_CTL_RST , mmio +HOST_EM_CTL ); +return 0 ; +} + +static int ahci_transmit_led_message (struct ata_port *ap,int led_num, +int state) +{ +struct ahci_host_priv *hpriv = ap->host->private_data; +void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR ]; +struct ahci_port_priv *pp = ap->private_data; +u32 em_ctl; +u32 message[] = {0 ,0 }; +unsigned int flags; + +spin_lock_irqsave (ap->lock, flags); + +/* +* if we are still busy transmitting a previous message, +* do not allow +*/ + em_ctl =readl (mmio +HOST_EM_CTL ); +if (em_ctl &EM_CTL_TM ) { +spin_unlock_irqrestore (ap->lock, flags); +return -EINVAL ; + } + +/* +* create message header - this is all zero except for +* the message size, which is 4 bytes. +*/ + message[0 ] |= (4 <<8 ); + + pp->led_state &= ~(9 << (3 *led_num)); + +/* +* create the actual message +* XXX will need Port Multiplier support +*/ + message[1 ] = (ap->port_no | (pp->led_state <<16 )); + +/* LED bit locations are determined by the led_num */ + message[1 ] |= (state << (16 + (3 *led_num))); + +/* write message to EM_LOC */ +writel (message[0 ], mmio + hpriv->em_loc); +writel (message[1 ], mmio + hpriv->em_loc+4 ); + +/* save off new led state */ + pp->led_state = ((message[1 ] >>16 ) &0x00ff ); + +/* +* tell hardware to transmit the message +*/ +writel (em_ctl |EM_CTL_TM , mmio +HOST_EM_CTL ); + +spin_unlock_irqrestore (ap->lock, flags); +return 0 ; +} + +static ssize_t ahci_led_store (struct device *dev,const char *buf,int num) +{ +struct scsi_device *sdev =to_scsi_device (dev); +struct ata_port *ap =ata_shost_to_port (sdev->host); +struct ata_device *atadev =ata_scsi_find_dev (ap, sdev); +int state; +int rc; + +if (!atadev || !ata_dev_enabled (atadev)) +return -EINVAL ; + + state =simple_strtoul (buf,NULL ,0 ); +if (state !=0 && state !=1 ) +return -EINVAL ; + + rc =ahci_transmit_led_message (ap, num, state); +if (!rc) +return count; +return rc; +} + +static ssize_t ahci_led_locate_store (struct device *dev, +struct device_attribute *attr,const char *buf,size_t count) +{ +ahci_led_store (dev, buf,1 ); +} +static DEVICE_ATTR(locate, S_IWUSR | S_IRUGO, NULL, ahci_led_locate_store); + +static ssize_t ahci_led_fault_store (struct device *dev, +struct device_attribute *attr,const char *buf,size_t count) +{ +ahci_led_store (dev, buf,2 ); +} +static DEVICE_ATTR(fault, S_IWUGO, NULL, ahci_led_fault_store); + +static struct device_attribute *ahci_em_led_attrs[] = { + &dev_attr_locate, + &dev_attr_fault, +NULL +}; +static void ahci_port_init (struct pci_dev *pdev,struct ata_port *ap,int port_no,void __iomem *mmio,void __iomem *port_mmio)
@@ -2178,7 +2303,8 @@ static void ahci_print_info(struct ata_host *host) dev_printk(KERN_INFO, &pdev->dev, "flags: " "%s%s%s%s%s%s%s" - "%s%s%s%s%s%s%s\n" + "%s%s%s%s%s%s%s" + "%s\n" , cap & (1 << 31) ? "64bit " : "",
@@ -2195,7 +2321,8 @@ static void ahci_print_info(struct ata_host *host) cap & (1 <<17 ) ?"pmp " :"" , cap & (1 <<15 ) ?"pio " :"" , cap & (1 <<14 ) ?"slum " :"" , - cap & (1 <<13 ) ?"part " :"" + cap & (1 <<13 ) ?"part " :"" , + cap & (1 <<6 ) ?"ems " :"" ); }
@@ -2331,6 +2458,27 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)ahci_init_controller (host);ahci_print_info (host); +if (ahci_em_messages && (hpriv->cap &HOST_CAP_EMS )) { +u8 messages; +void __iomem *mmio = host->iomap[AHCI_PCI_BAR ]; +u32 em_loc =readl (mmio +HOST_EM_LOC ); +u32 em_ctl =readl (mmio +HOST_EM_CTL ); + + messages = (em_ctl &0x000f0000 ) >>16 ; + +/* we only support LED message type right now */ +if ((messages &0x01 ) && (ahci_em_messages ==1 )) { +/* store em_loc */ + hpriv->em_loc = ((em_loc >>16 ) *4 ); + +/* reset the LEDs */ +ahci_reset_em (host); + +/* modify sht to add led sysfs files */ + ahci_sht.sdev_attrs = ahci_em_led_attrs; + } + } +pci_set_master (pdev);return ata_host_activate (host, pdev->irq, ahci_interrupt,IRQF_SHARED , &ahci_sht);
drivers/ata/libata-scsi.c +3 -2
@@ -55,7 +55,7 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc);static struct ata_device *__ata_scsi_find_dev (struct ata_port *ap,const struct scsi_device *scsidev); -static struct ata_device *ata_scsi_find_dev (struct ata_port *ap, +struct ata_device *ata_scsi_find_dev (struct ata_port *ap,const struct scsi_device *scsidev);static int ata_scsi_user_scan (struct Scsi_Host *shost,unsigned int channel,unsigned int id,unsigned int lun);
@@ -2593,7 +2593,7 @@ static int ata_scsi_dev_enabled(struct ata_device *dev)* RETURNS: * Associated ATA device, or %NULL if not found. */ -static struct ata_device * +struct ata_device *ata_scsi_find_dev (struct ata_port *ap,const struct scsi_device *scsidev) {struct ata_device *dev =__ata_scsi_find_dev (ap, scsidev);
@@ -2603,6 +2603,7 @@ ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev)return dev; } +EXPORT_SYMBOL_GPL (ata_scsi_find_dev);/* * ata_scsi_map_proto - Map pass-thru protocol value to taskfile value.
include/linux/libata.h +2 -0
@@ -900,6 +900,8 @@ extern int ata_scsi_slave_config(struct scsi_device *sdev);extern void ata_scsi_slave_destroy (struct scsi_device *sdev);extern int ata_scsi_change_queue_depth (struct scsi_device *sdev,int queue_depth); +struct ata_device *ata_scsi_find_dev (struct ata_port *ap, +const struct scsi_device *scsidev);extern struct ata_device *ata_dev_pair (struct ata_device *adev);extern int ata_do_set_mode (struct ata_link *link,struct ata_device **r_failed_dev);extern u8 ata_irq_on (struct ata_port *ap);
Signature · 1 line
1.5.3.4
Kristen wrote:
...
drivers/ata/ahci.c static int ahci_reset_controller(struct ata_host *host) · line 1146
Quoted 1 line
drivers/ata/ahci.c +1
-0+* XXX will need Port Multiplier support
What's that all about ?
Quoted 6 lines · On Thu, 29 Nov 2007 13:16:07 -0500 Mark Lord <[email protected]> wrote:
Kristen wrote:
...drivers/ata/ahci.c static int ahci_reset_controller(struct ata_host *host) · line 1146
Quoted 1 line
drivers/ata/ahci.c +1
-0+* XXX will need Port Multiplier support What's that all about ?
I didn't have any hardware that had LED support as well as Port Multiplier, so I didn't implement port multiplier support for this. I wasn't sure if it was better to just do it anyway, or leave it for when we actually have hardware that needs it.
Quoted 5 lines · Kristen Carlson Accardi
Quoted 2 lines · On Thu, 29 Nov 2007 13:16:07 -0500 Mark Lord <[email protected]> wrote:
Kristen wrote:
...
Quoted 8 lines
Quoted 3 lines
drivers/ata/ahci.c static int ahci_reset_controller(struct ata_host *host) · line 1146
Quoted 1 line
drivers/ata/ahci.c +1
-0+* XXX will need Port Multiplier support What's that all about ?
I didn't have any hardware that had LED support as well as Port Multiplier, so I didn't implement port multiplier support for this. I wasn't sure if it was better to just do it anyway, or leave it for when we actually have hardware that needs it.
..
Good. So please replace the "XXX" comment with the better explanation given in your posting above. That'll make future maintenance a lot less guessy.
Cheers
Quoted 2 lines · On Thu, 29 Nov 2007 09:48:02 -0800 Kristen Carlson Accardi…
This patch implements Enclosure Management via the LED protocol. See the AHCI 1.1 spec for details.
Whoops, I totally messed up and sent the wrong version of this patch. I'll send an updated one, ignore this.
Kristen
Quoted 296 lines
Signed-off-by Kristen Carlson Accardi <[email protected]>---
Here's a new version of the Enclosure management patch I sent a few weeks ago. I tried to incorporate all the feedback, although I'm still checking on whether it's ok to use these capability bits on a 1.0 ahci device. Please let me know if there are additional changes needed.drivers/ata/ahci.c | 152 ++++++++++++++++++++++++++++++++++++++++++++- drivers/ata/libata-scsi.c | 5 +- include/linux/libata.h | 2 + 3 files changed, 155 insertions(+), 4 deletions(-)drivers/ata/ahci.c +1
-0@@ -44,6 +44,7 @@#include <linux/dmi.h> #include <scsi/scsi_host.h> #include <scsi/scsi_cmnd.h> +#include <scsi/scsi_device.h> #include <linux/libata.h> #define DRV_NAME "ahci"@@ -92,6 +93,8 @@ enum {HOST_IRQ_STAT =0x08 ,/* interrupt status */ HOST_PORTS_IMPL = 0x0c, /* bitmap ofimplemented ports */
HOST_VERSION=0x10, /* AHCI
spec. version compliancy */drivers/ata/ahci.c +1
-0+ HOST_EM_LOC = 0x1c, /* Enclosure Managementlocation */
drivers/ata/ahci.c +1
-0+ HOST_EM_CTL = 0x20, /* Enclosure ManagementControl */
drivers/ata/ahci.c +0
-0/* HOST_CTL bits */ HOST_RESET = (1 << 0), /* reset controller;self-clear */ @@ -99,6 +102,7 @@ enum {
drivers/ata/ahci.c +1
-0HOST_AHCI_EN = (1 <<31 ),/* AHCI enabled */ /* HOST_CAP bits */ + HOST_CAP_EMS = (1 << 6), /* EnclosureManagement support */
HOST_CAP_SSC= (1 << 14), /*
Slumber capable */HOST_CAP_PMP= (1 << 17), /* Port
Multiplier support */HOST_CAP_CLO= (1 << 24), /*
Command List Override support */ @@ -193,6 +197,10 @@ enum {
ATA_FLAG_ACPI_SATA|ATA_FLAG_AN|ATA_FLAG_IPM,drivers/ata/ahci.c +4
-0AHCI_LFLAG_COMMON =ATA_LFLAG_SKIP_D2H_BSY , + +/* em_ctl bits */ +EM_CTL_RST = (1 <<9 ),/* Reset */ + EM_CTL_TM = (1 << 8), /* TransmitMessage */ };
struct
ahci_cmd_hdr{drivers/ata/ahci.c +0
-0@@ -216,6 +224,7 @@ struct ahci_host_priv {u32 port_map;/* port map to use */ u32
saved_cap; /* saved initial
cap */ u32saved_port_map; /* saved
initialport_map*/drivers/ata/ahci.c +1
-0+u32 em_loc;/* enclosure management location */ };
struct
ahci_port_priv{drivers/ata/ahci.c +0
-0@@ -231,6 +240,7 @@ struct ahci_port_priv { unsigned int ncq_saw_dmas:1; unsigned int ncq_saw_sdb:1;u32 intr_mask;/* interrupts to enable */
drivers/ata/ahci.c +1
-0+u16 led_state;/* saved current led state */ };
static int ahci_scr_read(struct
ata_port*ap, unsigned intsc_reg,
u32 *val); @@ -572,6 +582,11 @@ static structpci_driverahci_pci_driver= { #endif
};drivers/ata/ahci.c +5
-0+static int ahci_em_messages =1 ; +module_param (ahci_em_messages, int,0444 ); +/* add other LED protocol types when they become supported */ +MODULE_PARM_DESC(ahci_em_messages, + "Set AHCI Enclosure Management Message type (0 = disabled, 1= LED");
static inline intahci_nr_ports(u32 cap)
{drivers/ata/ahci.c +95
-0@@ -1082,6 +1097,116 @@ static int ahci_reset_controller(struct ata_host *host) return 0; } +/****** LED Enclosure Management routines ********/ +static int ahci_reset_em (struct ata_host *host) +{ +void __iomem *mmio = host->iomap[AHCI_PCI_BAR ]; +u32 em_ctl; + + em_ctl =readl (mmio +HOST_EM_CTL ); +if ((em_ctl &EM_CTL_TM ) || (em_ctl &EM_CTL_RST )) +return -EINVAL ; + +writel (em_ctl |EM_CTL_RST , mmio +HOST_EM_CTL ); +return 0 ; +} + +static int ahci_transmit_led_message (struct ata_port *ap,int led_num, +int state) +{ +struct ahci_host_priv *hpriv = ap->host->private_data; +void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR ]; +struct ahci_port_priv *pp = ap->private_data; +u32 em_ctl; +u32 message[] = {0 ,0 }; +unsigned int flags; + +spin_lock_irqsave (ap->lock, flags); + +/* +* if we are still busy transmitting a previous message, +* do not allow +*/ + em_ctl =readl (mmio +HOST_EM_CTL ); +if (em_ctl &EM_CTL_TM ) { +spin_unlock_irqrestore (ap->lock, flags); +return -EINVAL ; + } + +/* +* create message header - this is all zero except for +* the message size, which is 4 bytes. +*/ + message[0 ] |= (4 <<8 ); + + pp->led_state &= ~(9 << (3 *led_num)); + +/* +* create the actual message +* XXX will need Port Multiplier support +*/ + message[1 ] = (ap->port_no | (pp->led_state <<16 )); + +/* LED bit locations are determined by the led_num */ + message[1 ] |= (state << (16 + (3 *led_num))); + +/* write message to EM_LOC */ +writel (message[0 ], mmio + hpriv->em_loc); +writel (message[1 ], mmio + hpriv->em_loc+4 ); + +/* save off new led state */ + pp->led_state = ((message[1 ] >>16 ) &0x00ff ); + +/* +* tell hardware to transmit the message +*/ +writel (em_ctl |EM_CTL_TM , mmio +HOST_EM_CTL ); + +spin_unlock_irqrestore (ap->lock, flags); +return 0 ; +} + +static ssize_t ahci_led_store (struct device *dev,const char *buf, int num) +{ +struct scsi_device *sdev =to_scsi_device (dev); +struct ata_port *ap =ata_shost_to_port (sdev->host); +struct ata_device *atadev =ata_scsi_find_dev (ap, sdev); +int state; +int rc; + +if (!atadev || !ata_dev_enabled (atadev)) +return -EINVAL ; + + state =simple_strtoul (buf,NULL ,0 ); +if (state !=0 && state !=1 ) +return -EINVAL ; + + rc =ahci_transmit_led_message (ap, num, state); +if (!rc) +return count; +return rc; +} + +static ssize_t ahci_led_locate_store (struct device *dev, +struct device_attribute *attr,const char *buf,size_t count) +{ +ahci_led_store (dev, buf,1 ); +} +static DEVICE_ATTR(locate, S_IWUSR | S_IRUGO, NULL,
ahci_led_locate_store); +drivers/ata/ahci.c +38
-2+static ssize_t ahci_led_fault_store (struct device *dev, +struct device_attribute *attr,const char *buf,size_t count) +{ +ahci_led_store (dev, buf,2 ); +} +static DEVICE_ATTR(fault, S_IWUGO, NULL, ahci_led_fault_store); + +static struct device_attribute *ahci_em_led_attrs[] = { + &dev_attr_locate, + &dev_attr_fault, +NULL +}; +static void ahci_port_init (struct pci_dev *pdev,struct ata_port *ap,int port_no,void __iomem *mmio,void __iomem *port_mmio)@@ -2178,7 +2303,8 @@ static void ahci_print_info(struct ata_host *host) dev_printk(KERN_INFO, &pdev->dev, "flags: " "%s%s%s%s%s%s%s" - "%s%s%s%s%s%s%s\n" + "%s%s%s%s%s%s%s" + "%s\n" , cap & (1 << 31) ? "64bit " : "",@@ -2195,7 +2321,8 @@ static void ahci_print_info(struct ata_host *host) cap & (1 << 17) ? "pmp " : "", cap & (1 <<15 ) ?"pio " :"" , cap & (1 <<14 ) ?"slum " :"" , - cap & (1 <<13 ) ?"part " :"" + cap & (1 <<13 ) ?"part " :"" , + cap & (1 <<6 ) ?"ems " :"" ); }@@ -2331,6 +2458,27 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ahci_init_controller(host);ahci_print_info (host); +if (ahci_em_messages && (hpriv->cap &HOST_CAP_EMS )) { +u8 messages; +void __iomem *mmio = host->iomap[AHCI_PCI_BAR ]; +u32 em_loc =readl (mmio +HOST_EM_LOC ); +u32 em_ctl =readl (mmio +HOST_EM_CTL ); + + messages = (em_ctl &0x000f0000 ) >>16 ; + +/* we only support LED message type right now */ +if ((messages &0x01 ) && (ahci_em_messages ==1 )) { +/* store em_loc */ + hpriv->em_loc = ((em_loc >>16 ) *4 ); + +/* reset the LEDs */ +ahci_reset_em (host); + +/* modify sht to add led sysfs files */ + ahci_sht.sdev_attrs = ahci_em_led_attrs; + } + } +pci_set_master (pdev);return ata_host_activate (host, pdev->irq, ahci_interrupt,IRQF_SHARED , &ahci_sht);drivers/ata/libata-scsi.c +0
-0@@ -55,7 +55,7 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc);static struct ata_device *__ata_scsi_find_dev (struct ata_port *ap,const struct scsi_device *scsidev); -static struct ata_device *ata_scsi_find_dev(struct
ata_port*ap, +structata_device*ata_scsi_find_dev(structata_port*ap, const structscsi_device*scsidev);
static int ata_scsi_user_scan(structScsi_Host*shost, unsigned int
channel, unsigned int id, unsigned int lun);drivers/ata/libata-scsi.c +1
-1@@ -2593,7 +2593,7 @@ static int ata_scsi_dev_enabled(structata_device *dev) * RETURNS: * Associated ATA device, or %NULL if not found. */ -static struct ata_device * +struct ata_device *ata_scsi_find_dev (struct ata_port *ap,const struct scsi_device *scsidev) {drivers/ata/libata-scsi.c +1
-0struct ata_device *dev =__ata_scsi_find_dev (ap, scsidev);@@ -2603,6 +2603,7 @@ ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev)return dev; } +EXPORT_SYMBOL_GPL (ata_scsi_find_dev);/* * ata_scsi_map_proto - Map pass-thru protocol value to taskfile value. diff --git
a/include/linux/libata.hb/include/linux/libata.hindex ef52a07..1ccbd83 100644include/linux/libata.h +0
-0@@ -900,6 +900,8 @@ extern int ata_scsi_slave_config(struct
scsi_device*sdev); extern voidata_scsi_slave_destroy(struct scsi_device *sdev); extern intata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth);include/linux/libata.h +2
-0+struct ata_device *ata_scsi_find_dev (struct ata_port *ap, + const struct scsi_device*scsidev); extern struct
ata_device*ata_dev_pair(structata_device*adev); extern intata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev); extern u8ata_irq_on(struct ata_port *ap);
Hi!
drivers/ata/ahci.c static struct pci_driver ahci_pci_driver = { · line 589
Quoted 6 lines
drivers/ata/ahci.c +5
-0+static int ahci_em_messages =1 ; +module_param (ahci_em_messages, int,0444 ); +/* add other LED protocol types when they become supported */ +MODULE_PARM_DESC (ahci_em_messages, +"Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED" );
Should you add line in Doc* somewhere?
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html