This function works consistently for me (several cards, several drivers)
float lookupShadow(in sampler2DShadow dmap, in vec3 coord, in vec2 offset, const float size)
float depth = shadow2D(dmap, coord + vec3( offset.x, offset.y, 0.0)*size).r;
where dmap is the shadowmap (don't forget to set the uniform to the right texture image unit, bind it in code etc.), and size is the shadowmap size in pixels (e.g. 2048). Coord comes from the vertex shader
gl_TexCoord = gl_TextureMatrix * gl_ModelViewMatrix * gl_Vertex;
But you have to have the TextureMatrix for the shadows populated by the eye space->light space transformation, just like with hardware shadow maps.
Hope that helps. Shadows are tricky.