Now that probing is working in the new fashion, we need to go back to
having ata_getparm issue an ata_request and not fool around with the HW on its own. Needed for new HW support.
This commit is contained in:
parent
cc6dd6e064
commit
44e51c4adc
@ -68,7 +68,10 @@ static struct cdevsw ata_cdevsw = {
|
||||
/* prototypes */
|
||||
static void ata_interrupt(void *);
|
||||
static void ata_boot_attach(void);
|
||||
static device_t ata_add_child(device_t parent, struct ata_device *atadev, int unit);
|
||||
static device_t ata_add_child(device_t, struct ata_device *, int);
|
||||
static void bswap(int8_t *, int);
|
||||
static void btrim(int8_t *, int);
|
||||
static void bpack(int8_t *, int8_t *, int);
|
||||
|
||||
/* global vars */
|
||||
MALLOC_DEFINE(M_ATA, "ATA generic", "ATA driver generic layer");
|
||||
@ -566,7 +569,6 @@ ata_boot_attach(void)
|
||||
static device_t
|
||||
ata_add_child(device_t parent, struct ata_device *atadev, int unit)
|
||||
{
|
||||
struct ata_channel *ch = device_get_softc(parent);
|
||||
device_t child;
|
||||
|
||||
if ((child = device_add_child(parent, NULL, unit))) {
|
||||
@ -580,83 +582,146 @@ ata_add_child(device_t parent, struct ata_device *atadev, int unit)
|
||||
atadev->dev = child;
|
||||
atadev->max_iosize = DEV_BSIZE;
|
||||
atadev->mode = ATA_PIO_MAX;
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
static int
|
||||
ata_getparam(device_t parent, struct ata_device *atadev)
|
||||
{
|
||||
struct ata_channel *ch = device_get_softc(parent);
|
||||
struct ata_request *request;
|
||||
u_int8_t command = 0;
|
||||
int error = ENOMEM, retries = 2;
|
||||
|
||||
if (ch->devices &
|
||||
(atadev->unit == ATA_MASTER ? ATA_ATA_MASTER : ATA_ATA_SLAVE))
|
||||
command = ATA_ATA_IDENTIFY;
|
||||
if (ch->devices &
|
||||
(atadev->unit == ATA_MASTER ? ATA_ATAPI_MASTER : ATA_ATAPI_SLAVE))
|
||||
command = ATA_ATAPI_IDENTIFY;
|
||||
if (!command)
|
||||
return ENXIO;
|
||||
|
||||
while (retries-- > 0 && error) {
|
||||
if (!(request = ata_alloc_request()))
|
||||
break;
|
||||
request->dev = atadev->dev;
|
||||
request->timeout = 1;
|
||||
request->retries = 0;
|
||||
request->u.ata.command = command;
|
||||
request->flags = (ATA_R_READ|ATA_R_AT_HEAD|ATA_R_DIRECT|ATA_R_QUIET);
|
||||
request->data = (void *)&atadev->param;
|
||||
request->bytecount = sizeof(struct ata_params);
|
||||
request->donecount = 0;
|
||||
request->transfersize = DEV_BSIZE;
|
||||
ata_queue_request(request);
|
||||
error = request->result;
|
||||
ata_free_request(request);
|
||||
}
|
||||
|
||||
if (!error && (isprint(atadev->param.model[0]) ||
|
||||
isprint(atadev->param.model[1]))) {
|
||||
struct ata_params *atacap = &atadev->param;
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
int16_t *ptr;
|
||||
|
||||
for (ptr = (int16_t *)atacap;
|
||||
ptr < (int16_t *)atacap + sizeof(struct ata_params)/2; ptr++) {
|
||||
*ptr = bswap16(*ptr);
|
||||
}
|
||||
#endif
|
||||
if (!(!strncmp(atacap->model, "FX", 2) ||
|
||||
!strncmp(atacap->model, "NEC", 3) ||
|
||||
!strncmp(atacap->model, "Pioneer", 7) ||
|
||||
!strncmp(atacap->model, "SHARP", 5))) {
|
||||
bswap(atacap->model, sizeof(atacap->model));
|
||||
bswap(atacap->revision, sizeof(atacap->revision));
|
||||
bswap(atacap->serial, sizeof(atacap->serial));
|
||||
}
|
||||
btrim(atacap->model, sizeof(atacap->model));
|
||||
bpack(atacap->model, atacap->model, sizeof(atacap->model));
|
||||
btrim(atacap->revision, sizeof(atacap->revision));
|
||||
bpack(atacap->revision, atacap->revision, sizeof(atacap->revision));
|
||||
btrim(atacap->serial, sizeof(atacap->serial));
|
||||
bpack(atacap->serial, atacap->serial, sizeof(atacap->serial));
|
||||
if (bootverbose)
|
||||
printf("ata%d-%s: pio=%s wdma=%s udma=%s cable=%s wire\n",
|
||||
ch->unit, atadev->unit == ATA_MASTER ? "master":"slave",
|
||||
ata_mode2str(ata_pmode(atacap)),
|
||||
ata_mode2str(ata_wmode(atacap)),
|
||||
ata_mode2str(ata_umode(atacap)),
|
||||
(atacap->hwres & ATA_CABLE_ID) ? "80":"40");
|
||||
|
||||
if (atadev->param.config & ATA_PROTO_ATAPI) {
|
||||
if (atapi_dma && ch->dma &&
|
||||
if (atapi_dma && ch->dma &&
|
||||
(atadev->param.config & ATA_DRQ_MASK) != ATA_DRQ_INTR &&
|
||||
ata_umode(&atadev->param) >= ATA_UDMA2)
|
||||
ata_umode(&atadev->param) >= ATA_UDMA2)
|
||||
atadev->mode = ATA_DMA_MAX;
|
||||
}
|
||||
else {
|
||||
else {
|
||||
if (ata_dma && ch->dma)
|
||||
atadev->mode = ATA_DMA_MAX;
|
||||
}
|
||||
}
|
||||
return child;
|
||||
else {
|
||||
if (!error)
|
||||
error = ENXIO;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
ata_identify(device_t dev)
|
||||
{
|
||||
struct ata_channel *ch = device_get_softc(dev);
|
||||
struct ata_device *master, *slave;
|
||||
int master_res = EIO, slave_res = EIO, master_unit = -1, slave_unit = -1;
|
||||
struct ata_device *master = NULL, *slave = NULL;
|
||||
device_t master_child = NULL, slave_child = NULL;
|
||||
int master_unit = -1, slave_unit = -1;
|
||||
|
||||
if (!(master = malloc(sizeof(struct ata_device),
|
||||
M_ATA, M_NOWAIT | M_ZERO))) {
|
||||
device_printf(dev, "out of memory\n");
|
||||
return ENOMEM;
|
||||
if (ch->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER)) {
|
||||
if (!(master = malloc(sizeof(struct ata_device),
|
||||
M_ATA, M_NOWAIT | M_ZERO))) {
|
||||
device_printf(dev, "out of memory\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
master->unit = ATA_MASTER;
|
||||
}
|
||||
master->unit = ATA_MASTER;
|
||||
if (!(slave = malloc(sizeof(struct ata_device),
|
||||
M_ATA, M_NOWAIT | M_ZERO))) {
|
||||
free(master, M_ATA);
|
||||
device_printf(dev, "out of memory\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
slave->unit = ATA_SLAVE;
|
||||
|
||||
/* wait for the channel to be IDLE then grab it before touching HW */
|
||||
while (ATA_LOCKING(dev, ATA_LF_LOCK) != ch->unit)
|
||||
tsleep(ch, PRIBIO, "ataidnt1", 1);
|
||||
while (1) {
|
||||
mtx_lock(&ch->state_mtx);
|
||||
if (ch->state == ATA_IDLE) {
|
||||
ch->state = ATA_ACTIVE;
|
||||
mtx_unlock(&ch->state_mtx);
|
||||
break;
|
||||
}
|
||||
mtx_unlock(&ch->state_mtx);
|
||||
tsleep(ch, PRIBIO, "ataidnt2", 1);
|
||||
if (ch->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE)) {
|
||||
if (!(slave = malloc(sizeof(struct ata_device),
|
||||
M_ATA, M_NOWAIT | M_ZERO))) {
|
||||
free(master, M_ATA);
|
||||
device_printf(dev, "out of memory\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
slave->unit = ATA_SLAVE;
|
||||
}
|
||||
|
||||
if (ch->devices & ATA_ATA_SLAVE) {
|
||||
slave_res = ata_getparam(dev, slave, ATA_ATA_IDENTIFY);
|
||||
#ifdef ATA_STATIC_ID
|
||||
slave_unit = (device_get_unit(dev) << 1) + 1;
|
||||
#endif
|
||||
}
|
||||
else if (ch->devices & ATA_ATAPI_SLAVE)
|
||||
slave_res = ata_getparam(dev, slave, ATA_ATAPI_IDENTIFY);
|
||||
|
||||
if (ch->devices & ATA_ATA_MASTER) {
|
||||
master_res = ata_getparam(dev, master, ATA_ATA_IDENTIFY);
|
||||
#ifdef ATA_STATIC_ID
|
||||
if (ch->devices & ATA_ATA_MASTER)
|
||||
master_unit = (device_get_unit(dev) << 1);
|
||||
#endif
|
||||
}
|
||||
else if (ch->devices & ATA_ATAPI_MASTER)
|
||||
master_res = ata_getparam(dev, master, ATA_ATAPI_IDENTIFY);
|
||||
|
||||
if (master_res || !ata_add_child(dev, master, master_unit))
|
||||
if (master && !(master_child = ata_add_child(dev, master, master_unit))) {
|
||||
free(master, M_ATA);
|
||||
|
||||
if (slave_res || !ata_add_child(dev, slave, slave_unit))
|
||||
master = NULL;
|
||||
}
|
||||
#ifdef ATA_STATIC_ID
|
||||
if (ch->devices & ATA_ATA_SLAVE)
|
||||
slave_unit = (device_get_unit(dev) << 1) + 1;
|
||||
#endif
|
||||
if (slave && !(slave_child = ata_add_child(dev, slave, slave_unit))) {
|
||||
free(slave, M_ATA);
|
||||
slave = NULL;
|
||||
}
|
||||
|
||||
mtx_lock(&ch->state_mtx);
|
||||
ch->state = ATA_IDLE;
|
||||
mtx_unlock(&ch->state_mtx);
|
||||
ATA_LOCKING(dev, ATA_LF_UNLOCK);
|
||||
if (slave && ata_getparam(dev, slave)) {
|
||||
device_delete_child(dev, slave_child);
|
||||
free(slave, M_ATA);
|
||||
}
|
||||
if (master && ata_getparam(dev, master)) {
|
||||
device_delete_child(dev, master_child);
|
||||
free(master, M_ATA);
|
||||
}
|
||||
|
||||
bus_generic_probe(dev);
|
||||
bus_generic_attach(dev);
|
||||
@ -791,6 +856,51 @@ ata_limit_mode(struct ata_device *atadev, int mode, int maxmode)
|
||||
return mode;
|
||||
}
|
||||
|
||||
static void
|
||||
bswap(int8_t *buf, int len)
|
||||
{
|
||||
u_int16_t *ptr = (u_int16_t*)(buf + len);
|
||||
|
||||
while (--ptr >= (u_int16_t*)buf)
|
||||
*ptr = ntohs(*ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
btrim(int8_t *buf, int len)
|
||||
{
|
||||
int8_t *ptr;
|
||||
|
||||
for (ptr = buf; ptr < buf+len; ++ptr)
|
||||
if (!*ptr || *ptr == '_')
|
||||
*ptr = ' ';
|
||||
for (ptr = buf + len - 1; ptr >= buf && *ptr == ' '; --ptr)
|
||||
*ptr = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
bpack(int8_t *src, int8_t *dst, int len)
|
||||
{
|
||||
int i, j, blank;
|
||||
|
||||
for (i = j = blank = 0 ; i < len; i++) {
|
||||
if (blank && src[i] == ' ') continue;
|
||||
if (blank && src[i] != ' ') {
|
||||
dst[j++] = src[i];
|
||||
blank = 0;
|
||||
continue;
|
||||
}
|
||||
if (src[i] == ' ') {
|
||||
blank = 1;
|
||||
if (i == 0)
|
||||
continue;
|
||||
}
|
||||
dst[j++] = src[i];
|
||||
}
|
||||
if (j < len)
|
||||
dst[j] = 0x00;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* module handeling
|
||||
*/
|
||||
|
@ -471,7 +471,6 @@ void ata_fail_requests(struct ata_channel *ch, device_t dev);
|
||||
char *ata_cmd2str(struct ata_request *request);
|
||||
|
||||
/* ata-lowlevel.c: */
|
||||
int ata_getparam(device_t parent, struct ata_device *atadev, u_int8_t command);
|
||||
void ata_generic_hw(struct ata_channel *ch);
|
||||
void ata_generic_reset(struct ata_channel *ch);
|
||||
int ata_generic_command(struct ata_device *atadev, u_int8_t command, u_int64_t lba, u_int16_t count, u_int16_t feature);
|
||||
|
@ -54,100 +54,6 @@ static int ata_end_transaction(struct ata_request *);
|
||||
static int ata_wait(struct ata_channel *ch, struct ata_device *, u_int8_t);
|
||||
static void ata_pio_read(struct ata_request *, int);
|
||||
static void ata_pio_write(struct ata_request *, int);
|
||||
static void bswap(int8_t *, int);
|
||||
static void btrim(int8_t *, int);
|
||||
static void bpack(int8_t *, int8_t *, int);
|
||||
|
||||
/* get device parameter page from device */
|
||||
int
|
||||
ata_getparam(device_t parent, struct ata_device *atadev, u_int8_t command)
|
||||
{
|
||||
struct ata_channel *ch = device_get_softc(parent);
|
||||
int error = 0, retry = 0;
|
||||
|
||||
do {
|
||||
if (retry++ > 4) {
|
||||
if (bootverbose)
|
||||
printf("ata%d-%s: %s-identify retries exceeded\n", ch->unit,
|
||||
atadev->unit == ATA_MASTER ? "master" : "slave",
|
||||
command == ATA_ATAPI_IDENTIFY ? "ATAPI" : "ATA");
|
||||
error = ENXIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* select device */
|
||||
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | atadev->unit);
|
||||
|
||||
/* wait a bit to let slow devices settle */
|
||||
DELAY(100);
|
||||
|
||||
/* disable interrupt */
|
||||
ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT | ATA_A_IDS);
|
||||
|
||||
/* ready to issue command ? */
|
||||
if ((error = ata_wait(ch, atadev, 0)) < 0) {
|
||||
printf("ata%d-%s: timeout sending %s-identify error=%d\n",
|
||||
device_get_unit(parent),
|
||||
atadev->unit == ATA_MASTER ? "master" : "slave",
|
||||
command == ATA_ATAPI_IDENTIFY ? "ATAPI" : "ATA", error);
|
||||
error = ENXIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* select device */
|
||||
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | atadev->unit);
|
||||
|
||||
/* issue command */
|
||||
ATA_IDX_OUTB(ch, ATA_COMMAND, command);
|
||||
|
||||
} while (ata_wait(ch, atadev, ATA_S_DRQ));
|
||||
|
||||
if (!error) {
|
||||
ATA_IDX_INSW_STRM(ch, ATA_DATA, (void *)&atadev->param,
|
||||
sizeof(struct ata_params)/sizeof(int16_t));
|
||||
ATA_IDX_INB(ch, ATA_STATUS);
|
||||
}
|
||||
|
||||
if (!error && (isprint(atadev->param.model[0]) ||
|
||||
isprint(atadev->param.model[1]))) {
|
||||
struct ata_params *atacap = &atadev->param;
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
int16_t *ptr;
|
||||
|
||||
for (ptr = (int16_t *)atacap;
|
||||
ptr < (int16_t *)atacap + sizeof(struct ata_params)/2; ptr++) {
|
||||
*ptr = bswap16(*ptr);
|
||||
}
|
||||
#endif
|
||||
if (!(!strncmp(atacap->model, "FX", 2) ||
|
||||
!strncmp(atacap->model, "NEC", 3) ||
|
||||
!strncmp(atacap->model, "Pioneer", 7) ||
|
||||
!strncmp(atacap->model, "SHARP", 5))) {
|
||||
bswap(atacap->model, sizeof(atacap->model));
|
||||
bswap(atacap->revision, sizeof(atacap->revision));
|
||||
bswap(atacap->serial, sizeof(atacap->serial));
|
||||
}
|
||||
btrim(atacap->model, sizeof(atacap->model));
|
||||
bpack(atacap->model, atacap->model, sizeof(atacap->model));
|
||||
btrim(atacap->revision, sizeof(atacap->revision));
|
||||
bpack(atacap->revision, atacap->revision, sizeof(atacap->revision));
|
||||
btrim(atacap->serial, sizeof(atacap->serial));
|
||||
bpack(atacap->serial, atacap->serial, sizeof(atacap->serial));
|
||||
if (bootverbose)
|
||||
printf("ata%d-%s: pio=%s wdma=%s udma=%s cable=%s wire\n",
|
||||
ch->unit, atadev->unit == ATA_MASTER ? "master":"slave",
|
||||
ata_mode2str(ata_pmode(atacap)),
|
||||
ata_mode2str(ata_wmode(atacap)),
|
||||
ata_mode2str(ata_umode(atacap)),
|
||||
(atacap->hwres & ATA_CABLE_ID) ? "80":"40");
|
||||
}
|
||||
else {
|
||||
if (!error)
|
||||
error = ENXIO;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* low level ATA functions
|
||||
@ -948,47 +854,3 @@ ata_pio_write(struct ata_request *request, int length)
|
||||
ATA_IDX_OUTW(ch, ATA_DATA, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bswap(int8_t *buf, int len)
|
||||
{
|
||||
u_int16_t *ptr = (u_int16_t*)(buf + len);
|
||||
|
||||
while (--ptr >= (u_int16_t*)buf)
|
||||
*ptr = ntohs(*ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
btrim(int8_t *buf, int len)
|
||||
{
|
||||
int8_t *ptr;
|
||||
|
||||
for (ptr = buf; ptr < buf+len; ++ptr)
|
||||
if (!*ptr || *ptr == '_')
|
||||
*ptr = ' ';
|
||||
for (ptr = buf + len - 1; ptr >= buf && *ptr == ' '; --ptr)
|
||||
*ptr = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
bpack(int8_t *src, int8_t *dst, int len)
|
||||
{
|
||||
int i, j, blank;
|
||||
|
||||
for (i = j = blank = 0 ; i < len; i++) {
|
||||
if (blank && src[i] == ' ') continue;
|
||||
if (blank && src[i] != ' ') {
|
||||
dst[j++] = src[i];
|
||||
blank = 0;
|
||||
continue;
|
||||
}
|
||||
if (src[i] == ' ') {
|
||||
blank = 1;
|
||||
if (i == 0)
|
||||
continue;
|
||||
}
|
||||
dst[j++] = src[i];
|
||||
}
|
||||
if (j < len)
|
||||
dst[j] = 0x00;
|
||||
}
|
||||
|
@ -454,6 +454,7 @@ ata_timeout(struct ata_request *request)
|
||||
if (ch->state == ATA_ACTIVE || ch->state == ATA_STALL_QUEUE) {
|
||||
request->flags |= ATA_R_TIMEOUT;
|
||||
ch->state |= ATA_TIMEOUT;
|
||||
ch->running = NULL;
|
||||
mtx_unlock(&ch->state_mtx);
|
||||
ATA_LOCKING(ch->dev, ATA_LF_UNLOCK);
|
||||
ata_finish(request);
|
||||
|
Loading…
Reference in New Issue
Block a user