pcdisk.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/dditypes.h>
#include <sys/dditypes.h>
#define MIN_SEC_SIZE 512
/*
* Queue a request and call start routine.
*
* If the request is not a special buffer request,
* do validation on it and generate both an absolute
* block number (which we will leave in b_resid),
* and a actual block count value (which we will
* leave in av_back).
*/
int
{
void *instance;
int part;
int ret;
#ifdef ATA_DEBUG
if (pcata_debug & DIO)
#endif
&instance) != DDI_SUCCESS) {
return (0);
}
return (0);
}
if (!(CARD_PRESENT_VALID(softp))) {
#ifdef ATA_DEBUG
if (pcata_debug & DIO)
(void *)bp);
#endif
return (0);
}
return (0);
}
#ifdef ATA_DEBUG
if (pcata_debug & DIO) {
}
#endif
/*
* pointer to structure for physical drive
*/
/*
* (aka the UNIT macro) this means only 1 physical disk
* this error occurs everywhere ab_link is used!
*/
if (!unitp) {
return (0);
}
/*
*
* If the transfer size would take it past the end of the
* partition, trim it down. Also trim it down to a multiple
* of the block size.
*/
/*
* Map block number within partition to absolute
* block number.
*/
#ifdef ATA_DEBUG
if (pcata_debug & DIO)
"%c%d: %s block %ld mapped to %ld dev %lx\n",
#endif
/* make sure this partition exists */
#ifdef ATA_DEBUG
#endif
return (0);
}
/* make sure the I/O begins at a block within the partition */
#ifdef ATA_DEBUG
#endif
return (0);
}
/* put block number into b_resid and number of blocks into av_back */
if (ret != CTL_SEND_SUCCESS) {
#ifdef ATA_DEBUG
(void *)bp);
#endif
return (0);
}
/*
* If the disk block to be written to is disk block 0, it would
* mean the partition table is changing from underneath us
* we shoud trap and update the in memory image.
* By now the buffer is mapped in and we should be able to
* use the contents as the new fdisk partition.
*/
blkno == 0) {
return (0);
}
}
return (0);
}
/*
* This routine implements the ioctl calls for the ATA
*/
#define COPYOUT(a, b, c, f) \
#define COPYIN(a, b, c, f) \
/* ARGSUSED3 */
int
int cmd,
int flag,
int *rval_p)
{
void *instance;
int i, status;
int err;
enum dkio_state state;
#ifdef ATA_DEBUG
#endif
&instance) != DDI_SUCCESS)
return (ENODEV);
return (ENXIO);
}
#ifdef ATA_DEBUG
if (pcata_debug & DENT) {
char *cmdname;
switch (cmd) {
default: cmdname = "UNKNOWN *"; break;
}
"_ioctl%d: cmd %x(%s) arg %p softp %p\n",
(void *)softp);
}
#endif
/*
* We should process DKIOCSTATE cmd even if CARD is not PRESENT.
* The DKIOCSTATE command should BLOCK if there is no change in state.
* Only when softp->state != state the control returns to the caller.
* This check is done in pcata_check_media().
* There are 3 states for the device.
* DKIO_NONE
* DKIO_INSERTED
* DKIO_EJECTED
* The state transitions are as follows
* DKIO_NONE-DKIO_INSERTED-DKIO_EJECTED-DKIO_NONE-DKIO_INSERTED...
*/
if (cmd == DKIOCSTATE) {
return (EFAULT);
}
/*
* This function is used by the volume management
* to check the pcata card state
*/
return (err);
}
return (EFAULT);
}
return (0);
}
if (!(CARD_PRESENT_VALID(softp))) {
return (ENODEV);
}
/*
* we can respond to get geom ioctl() only while the driver has
* not completed initialization.
*/
(void) pcata_readywait(softp);
return (EFAULT);
}
switch (cmd) {
case DKIOCGGEOM:
case DKIOCSGEOM:
case DKIOCGAPART:
case DKIOCSAPART:
case DKIOCGVTOC:
case DKIOCSVTOC:
status = 0;
return (status);
}
switch (cmd) {
case DKIOCINFO:
/*
* Controller Information
*/
/*
* Unit Information
*/
/*
* We can't get from here to there yet
*/
return (EFAULT);
break;
case DKIOCG_VIRTGEOM:
case DKIOCG_PHYGEOM:
{
status = 0;
if (unitp != 0) {
} else
if (status)
return (EFAULT);
return (EFAULT);
else
return (0);
}
case DKIOCGMEDIAINFO:
{
struct dk_minfo media_info;
int secsize;
/*
* atarp_secsize contains the unformatted sector size.
* Using this we determine the actual sector size.
* sector sizes are a multiple of MIN_SEC_SIZE(512).
*/
return (EFAULT);
else
return (0);
}
case DKIOCREMOVABLE:
{
/*
* Supporting volmgt by returning a constant
* since PCMCIA is a removable media.
* Refer to PSARC/1996/004.
*/
i = 1;
flag)) {
return (EFAULT);
}
break;
}
case DIOCTL_RWCMD:
{
int rw;
int status;
struct dadkio_rwcmd rwcmd;
#if defined(_MULTI_DATAMODEL)
case DDI_MODEL_ILP32: {
struct dadkio_rwcmd32 rwcmd32;
sizeof (struct dadkio_rwcmd32), flag)) {
return (EFAULT);
}
break;
}
case DDI_MODEL_NONE:
sizeof (struct dadkio_rwcmd), flag)) {
return (EFAULT);
}
break;
}
#else /* _MULTI_DATAMODEL */
sizeof (struct dadkio_rwcmd), flag)) {
return (EFAULT);
}
#endif /* _MULTI_DATAMODEL */
case DADKIO_RWCMD_READ:
break;
case DADKIO_RWCMD_WRITE:
break;
default:
return (EINVAL);
}
return (status);
}
case DKIOCEJECT:
/*
* Since we do not have hardware support for ejecting
* a pcata card, we must not support the generic eject
* ioctl (DKIOCEJECT) which is used for eject(1) command
* because it leads the user to expect behavior that is
* not present.
*/
return (ENOSYS);
case HDKIOCSCMD:
case HDKIOCGDIAG:
break;
default:
return (ENOTTY);
}
return (0);
}
int
{
void *instance;
int i;
&instance) != DDI_SUCCESS)
return (ENODEV);
return (ENXIO);
}
if (!(CARD_PRESENT_VALID(softp))) {
return (ENODEV);
}
switch (cmd) {
case DKIOCGGEOM:
case DKIOCGAPART:
case DKIOCGVTOC:
return (EFAULT);
}
switch (cmd) {
case DKIOCGGEOM:
{
return (EFAULT);
}
break;
}
case DKIOCSGEOM:
i = sizeof (struct dk_geom);
return (EFAULT);
break;
case DKIOCGAPART:
/*
* Return the map for all logical partitions.
*/
#if defined(_MULTI_DATAMODEL)
case DDI_MODEL_ILP32: {
int i;
for (i = 0; i < NDKMAP; i++) {
}
return (EFAULT);
break;
}
case DDI_MODEL_NONE:
return (EFAULT);
break;
}
#else /* _MULTI_DATAMODEL */
return (EFAULT);
#endif /* _MULTI_DATAMODEL */
break;
case DKIOCSAPART:
/*
* Set the map for all logical partitions.
*/
#if defined(_MULTI_DATAMODEL)
case DDI_MODEL_ILP32: {
int i;
return (EFAULT);
for (i = 0; i < NDKMAP; i++) {
}
break;
}
case DDI_MODEL_NONE:
return (EFAULT);
break;
}
break;
#else /* _MULTI_DATAMODEL */
return (EFAULT);
break;
#endif /* _MULTI_DATAMODEL */
case DKIOCGVTOC:
#if defined(_MULTI_DATAMODEL)
case DDI_MODEL_ILP32: {
return (EFAULT);
break;
}
case DDI_MODEL_NONE:
return (EFAULT);
break;
}
return (0);
#else /* _MULTI_DATAMODEL */
return (EFAULT);
return (0);
#endif /* _MULTI_DATAMODEL */
case DKIOCSVTOC:
#if defined(_MULTI_DATAMODEL)
case DDI_MODEL_ILP32: {
return (EFAULT);
return (EFAULT);
break;
}
case DDI_MODEL_NONE:
return (EFAULT);
return (EFAULT);
break;
}
#else /* _MULTI_DATAMODEL */
return (EFAULT);
return (EFAULT);
break;
#endif /* _MULTI_DATAMODEL */
}
return (0);
}
/* ARGSUSED */
int
{
void *instance;
int i;
#ifdef ATA_DEBUG
if (pcata_debug & DIO)
"dev_p=%p dev=%x flag=%x otyp=%x cred_p=%p\n",
#endif
&instance) != DDI_SUCCESS)
return (ENODEV);
/*
* open and getinfo may be called before attach completes
*/
for (i = 0; i < 300; i++) {
break;
drv_usecwait(10000);
}
if (!pcata_readywait(softp))
return (ENXIO);
#ifdef ATA_DEBUG
if (pcata_debug & DIO)
"_open: part=%d blk_open=%x chr_open=%x lyr_open=%d\n",
#endif
/*
* Only honor FEXCL. If a regular open or a layered open
* is still outstanding on the device, the exclusive open
* must fail.
*/
return (EAGAIN);
}
}
switch (otyp) {
case OTYP_BLK:
break;
case OTYP_CHR:
break;
case OTYP_LYR:
break;
default:
return (EINVAL);
}
return (0);
}
/* ARGSUSED */
int
{
int i;
int lyr_count = 0;
void *instance;
#ifdef ATA_DEBUG
if (pcata_debug & DIO)
#endif
&instance) != DDI_SUCCESS)
return (ENODEV);
#ifdef ATA_DEBUG
if (pcata_debug & DIO)
"_close: part=%d blk_open=%x chr_open=%x lyr_open=%d\n",
#endif
switch (otyp) {
case OTYP_BLK:
break;
case OTYP_CHR:
break;
case OTYP_LYR:
break;
default:
return (EINVAL);
}
/* not done yet */
return (0);
} else {
lyr_count++;
}
if (lyr_count) {
/* not done yet */
return (0);
}
}
if (softp->ejected_while_mounted)
softp->ejected_while_mounted = 0;
return (0);
}
static int
{
int status;
if (!unitp)
return (EFAULT);
return (EFAULT);
/* release buffer allocated by getrbuf */
if (status == DDI_FAILURE)
return (EFAULT);
return (0);
}
/*
*
*/
int
{
int status;
if (!unitp)
return (EFAULT);
return (EFAULT);
/*
* The dev is passed here for use later by the dsklbl_rdvtoc()
* and pcata_dsklbl_read_label() to check for card present before
* calling biowait.
*/
/* release buffer allocated by getrbuf */
if (status == DDI_FAILURE)
return (EFAULT);
return (0);
}
static buf_t *
{
char *secbuf;
/* allocate memory to hold disk label */
if (!secbuf)
return (NULL);
/* allocate a buf_t to manage the disk label block */
if (!bp) {
return (NULL);
}
/* initialize the buf_t */
return (bp);
}
int
{
int status;
return (EFAULT);
#ifdef ATA_DEBUG
#endif
/* release buffer allocated by getrbuf */
return (status);
}
/*
*/
static int
{
int err;
/*
* Do a CS call to see if the card is present
*/
!= CS_SUCCESS) {
(void) csx_Error2Text(&cft);
"GetStatus failed %s (0x%x)\n",
return (ENXIO);
}
/* Register rs->media_state */
} else {
} else {
}
}
/*
* XXXX - In order not to modify the volume management
* we have to follow the current SCSI CDROM model
* for checking media state (broken way, sigh!)
* start with state = DKIO_NONE
* wait until mediastate = DKIO_INSERTED
* wait until mediastate = DKIO_EJECTED
* if DKIOCSTATE ioctl() is called second time
* with state = DKIO_EJECTED,
* return state = DKIO_NONE
* restart with state = DKIO_NONE
*
*/
if (rs->ejected_media_flag &&
rs->ejected_media_flag = 0;
return (0);
}
}
#ifdef ATA_DEBUG
if (pcata_debug & DVOLD) {
"\tWaiting state change: rs->media_state %d state %d\n"
"\tDKIO_NONE %d DKIO_EJECTED %d DKIO_INSERTED %d\n",
}
#endif
/*
* wait for Card Detect Change Interrupt handler
* see either pcata_card_insertion/pcata_card_removal
* for cv_broadcast
*/
rs->checkmedia_flag++;
return (EINTR);
}
}
#ifdef ATA_DEBUG
if (pcata_debug & DVOLD) {
"\tAfter state change: rs->media_state %d state %d\n"
"\tDKIO_NONE %d DKIO_EJECTED %d DKIO_INSERTED %d\n",
}
#endif
if (!rs->ejected_media_flag &&
rs->ejected_media_flag++;
}
}
return (0);
}
int
{
/*
* Our dynamic properties are all device specific and size oriented.
* Requests issued under conditions where size is valid are passed
* to ddi_prop_op_nblocks with the size information, otherwise the
* request is passed to ddi_prop_op.
*/
!(CARD_PRESENT_VALID(softp)) ||
} else {
/* get nblocks value */
}
}