Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/bd/ata_bd/ata_bd.c

    raa893e0 rff65e91  
    5151#include <libarch/ddi.h>
    5252#include <ddi.h>
    53 #include <ipc/ipc.h>
    5453#include <ipc/bd.h>
    5554#include <async.h>
     
    8281static const size_t identify_data_size = 512;
    8382
    84 /** Size of the communication area. */
    85 static size_t comm_size;
    86 
    8783/** I/O base address of the command registers. */
    8884static uintptr_t cmd_physical;
     
    106102static void print_syntax(void);
    107103static int ata_bd_init(void);
    108 static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
     104static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *);
    109105static int ata_bd_read_blocks(int disk_id, uint64_t ba, size_t cnt,
    110106    void *buf);
     
    275271
    276272/** Block device connection handler */
    277 static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall)
     273static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    278274{
    279275        void *fs_va = NULL;
     
    282278        sysarg_t method;
    283279        devmap_handle_t dh;
    284         int flags;
     280        size_t comm_size;       /**< Size of the communication area. */
     281        unsigned int flags;
    285282        int retval;
    286283        uint64_t ba;
     
    298295
    299296        if (disk_id < 0 || disk[disk_id].present == false) {
    300                 ipc_answer_0(iid, EINVAL);
     297                async_answer_0(iid, EINVAL);
    301298                return;
    302299        }
    303300
    304301        /* Answer the IPC_M_CONNECT_ME_TO call. */
    305         ipc_answer_0(iid, EOK);
     302        async_answer_0(iid, EOK);
    306303
    307304        if (!async_share_out_receive(&callid, &comm_size, &flags)) {
    308                 ipc_answer_0(callid, EHANGUP);
     305                async_answer_0(callid, EHANGUP);
    309306                return;
    310307        }
     
    312309        fs_va = as_get_mappable_page(comm_size);
    313310        if (fs_va == NULL) {
    314                 ipc_answer_0(callid, EHANGUP);
     311                async_answer_0(callid, EHANGUP);
    315312                return;
    316313        }
     
    318315        (void) async_share_out_finalize(callid, fs_va);
    319316
    320         while (1) {
     317        while (true) {
    321318                callid = async_get_call(&call);
    322319                method = IPC_GET_IMETHOD(call);
     320               
     321                if (!method) {
     322                        /* The other side has hung up. */
     323                        async_answer_0(callid, EOK);
     324                        return;
     325                }
     326               
    323327                switch (method) {
    324                 case IPC_M_PHONE_HUNGUP:
    325                         /* The other side has hung up. */
    326                         ipc_answer_0(callid, EOK);
    327                         return;
    328328                case BD_READ_BLOCKS:
    329329                        ba = MERGE_LOUP32(IPC_GET_ARG1(call),
     
    347347                        break;
    348348                case BD_GET_BLOCK_SIZE:
    349                         ipc_answer_1(callid, EOK, disk[disk_id].block_size);
     349                        async_answer_1(callid, EOK, disk[disk_id].block_size);
    350350                        continue;
    351351                case BD_GET_NUM_BLOCKS:
    352                         ipc_answer_2(callid, EOK, LOWER32(disk[disk_id].blocks),
     352                        async_answer_2(callid, EOK, LOWER32(disk[disk_id].blocks),
    353353                            UPPER32(disk[disk_id].blocks));
    354354                        continue;
     
    357357                        break;
    358358                }
    359                 ipc_answer_0(callid, retval);
     359                async_answer_0(callid, retval);
    360360        }
    361361}
     
    373373        uint16_t w;
    374374        uint8_t c;
     375        uint16_t bc;
    375376        size_t pos, len;
    376377        int rc;
     
    388389        } else if (rc == EIO) {
    389390                /*
    390                  * There is something, but not a register device.
    391                  * It could be a packet device.
     391                 * There is something, but not a register device. Check to see
     392                 * whether the IDENTIFY command left the packet signature in
     393                 * the registers in case this is a packet device.
     394                 *
     395                 * According to the ATA specification, the LBA low and
     396                 * interrupt reason registers should be set to 0x01. However,
     397                 * there are many devices that do not follow this and only set
     398                 * the byte count registers. So, only check these.
    392399                 */
    393                 rc = identify_pkt_dev(disk_id, &idata);
    394                 if (rc == EOK) {
    395                         /* We have a packet device. */
    396                         d->dev_type = ata_pkt_dev;
     400                bc = ((uint16_t)pio_read_8(&cmd->cylinder_high) << 8) |
     401                    pio_read_8(&cmd->cylinder_low);
     402
     403                if (bc == PDEV_SIGNATURE_BC) {
     404                        rc = identify_pkt_dev(disk_id, &idata);
     405                        if (rc == EOK) {
     406                                /* We have a packet device. */
     407                                d->dev_type = ata_pkt_dev;
     408                        } else {
     409                                return EIO;
     410                        }
    397411                } else {
    398412                        /* Nope. Something's there, but not recognized. */
     
    404418        }
    405419
    406         printf("device caps: 0x%04x\n", idata.caps);
    407420        if (d->dev_type == ata_pkt_dev) {
    408421                /* Packet device */
     
    567580
    568581        /*
    569          * This is where we would most likely expect a non-existing device to
    570          * show up by not setting SR_DRDY.
     582         * Do not wait for DRDY to be set in case this is a packet device.
     583         * We determine whether the device is present by waiting for DRQ to be
     584         * set after issuing the command.
    571585         */
    572         if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
     586        if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
    573587                return ETIMEOUT;
    574588
     
    578592                return ETIMEOUT;
    579593
     594        /*
     595         * If ERR is set, this may be a packet device, so return EIO to cause
     596         * the caller to check for one.
     597         */
     598        if ((status & SR_ERR) != 0) {
     599                return EIO;
     600        }
     601
     602        if (wait_status(SR_DRQ, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK)
     603                return ETIMEOUT;
     604
    580605        /* Read data from the disk buffer. */
    581606
    582         if ((status & SR_DRQ) != 0) {
    583                 for (i = 0; i < identify_data_size / 2; i++) {
    584                         data = pio_read_16(&cmd->data_port);
    585                         ((uint16_t *) buf)[i] = data;
    586                 }
    587         }
    588 
    589         if ((status & SR_ERR) != 0) {
    590                 return EIO;
     607        for (i = 0; i < identify_data_size / 2; i++) {
     608                data = pio_read_16(&cmd->data_port);
     609                ((uint16_t *) buf)[i] = data;
    591610        }
    592611
Note: See TracChangeset for help on using the changeset viewer.