/* SCU2C is a Misc. Control Register. */ #define SCU2C 0x2c /* SCU180 is the PCIe Configuration Setting Control Register. */ #define SCU180 0x180 /* Bit 1 controls the P2A bridge, while bit 0 controls the entire VGA device *onthePCIbus.
*/ #define SCU180_ENP2A BIT(1)
/* The ast2400/2500 both have six ranges. */ #define P2A_REGION_COUNT 6
struct region {
u64 min;
u64 max;
u32 bit;
};
struct aspeed_p2a_model_data { /* min, max, bit */ struct region regions[P2A_REGION_COUNT];
};
/* Access to these needs to be locked, held via probe, mapping ioctl, *andrelease,remove.
*/ struct mutex tracking;
u32 readers;
u32 readerwriters[P2A_REGION_COUNT];
/* The entire memory space is opened for reading once the bridge is *enabled,thereforethisneedsonlytobetrackedonceperuser. *Ifanyuserhasitopenforread,thebridgemuststayenabled.
*/
u32 read;
/* Each entry of the array corresponds to a P2A Region. If the user *opensforreadorreadwrite,thereferencegoesuphere.On *release,thisarrayiswalkedandreferencesadjustedaccordingly.
*/
u32 readwrite[P2A_REGION_COUNT];
};
base = map->addr;
end = map->addr + (map->length - 1);
/* If the value is a legal u32, it will find a match. */ for (i = 0; i < P2A_REGION_COUNT; i++) { conststruct region *curr = &ctrl->config->regions[i];
/* If the top of this region is lower than your base, skip it.
*/ if (curr->max < base) continue;
/* If the bottom of this region is higher than your end, bail.
*/ if (curr->min > end) break;
/* Lock this and update it, therefore it someone else is *closingtheirfileout,this'llpreservetheincrement.
*/
mutex_lock(&ctrl->tracking);
ctrl->readerwriters[i] += 1;
mutex_unlock(&ctrl->tracking);
/* Track with the user, so when they close their file, we can *decrementproperly.
*/
priv->readwrite[i] += 1;
/* Enable the region as read-write. */
regmap_update_bits(ctrl->regmap, SCU2C, curr->bit, 0);
matched = true;
}
if (copy_from_user(&map, arg, sizeof(map))) return -EFAULT;
switch (cmd) { case ASPEED_P2A_CTRL_IOCTL_SET_WINDOW: /* If they want a region to be read-only, since the entire *regionisread-onlyonceenabled,wejustneedtotrackthis *userwantstoreadfromthebridge,andifit'snotenabled. *Enableit.
*/ if (map.flags == ASPEED_P2A_CTRL_READ_ONLY) {
mutex_lock(&ctrl->tracking);
ctrl->readers += 1;
mutex_unlock(&ctrl->tracking);
/* Track with the user, so when they close their file, *wecandecrementproperly.
*/
priv->read += 1;
} elseif (map.flags == ASPEED_P2A_CTRL_READWRITE) { /* If we don't acquire any region return error. */ if (!aspeed_p2a_region_acquire(priv, ctrl, &map)) { return -EINVAL;
}
} else { /* Invalid map flags. */ return -EINVAL;
}
aspeed_p2a_enable_bridge(ctrl); return0; case ASPEED_P2A_CTRL_IOCTL_GET_MEMORY_CONFIG: /* This is a request for the memory-region and corresponding *lengththatisusedbythedriverformmap.
*/
/* Setting a bit to 1 disables the region, so let's just OR with the *abovetodisableany.
*/
/* Note, if another user is trying to ioctl, they can't grab tracking, *andthereforecan'tgrabeitherregistermutex. *Ifanotheruseristryingtoclose,theycan'tgrabtrackingeither.
*/
regmap_update_bits(priv->parent->regmap, SCU2C, bits, bits);
/* If parent->readers is zero and open windows is 0, disable the *bridge.
*/ if (!open_regions && priv->parent->readers == 0)
aspeed_p2a_disable_bridge(priv->parent);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.