⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cdu31a.c.txt

📁 Linux块设备驱动分析与模拟实现
💻 TXT
📖 第 1 页 / 共 4 页
字号:
1393       final_pos_msf[0] = params[4];
1394       final_pos_msf[1] = params[5];
1395       final_pos_msf[2] = params[6];
1396       sony_audio_status = CDROM_AUDIO_PLAY;
1397       return 0;
1398       break;
1399 
1400    case CDROMREADTOCHDR:        /* Read the table of contents header */
1401       {
1402          struct cdrom_tochdr *hdr;
1403          struct cdrom_tochdr loc_hdr;
1404          
1405          sony_get_toc();
1406          if (!sony_toc_read)
1407          {
1408             return -EIO;
1409          }
1410          
1411          hdr = (struct cdrom_tochdr *) arg;
1412          verify_area(VERIFY_WRITE, hdr, sizeof(*hdr));
1413          loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num);
1414          loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num);
1415          memcpy_tofs(hdr, &loc_hdr, sizeof(*hdr));
1416       }
1417       return 0;
1418       break;
1419 
1420    case CDROMREADTOCENTRY:      /* Read a given table of contents entry */
1421       {
1422          struct cdrom_tocentry *entry;
1423          struct cdrom_tocentry loc_entry;
1424          int track_idx;
1425          unsigned char *msf_val = NULL;
1426          
1427          sony_get_toc();
1428          if (!sony_toc_read)
1429          {
1430             return -EIO;
1431          }
1432          
1433          entry = (struct cdrom_tocentry *) arg;
1434          verify_area(VERIFY_READ, entry, sizeof(*entry));
1435          verify_area(VERIFY_WRITE, entry, sizeof(*entry));
1436          
1437          memcpy_fromfs(&loc_entry, entry, sizeof(loc_entry));
1438          
1439          /* Lead out is handled separately since it is special. */
1440          if (loc_entry.cdte_track == CDROM_LEADOUT)
1441          {
1442             loc_entry.cdte_adr = sony_toc->address2;
1443             loc_entry.cdte_ctrl = sony_toc->control2;
1444             msf_val = sony_toc->lead_out_start_msf;
1445          }
1446          else
1447          {
1448             track_idx = find_track(int_to_bcd(loc_entry.cdte_track));
1449             if (track_idx < 0)
1450             {
1451                return -EINVAL;
1452             }
1453             
1454             loc_entry.cdte_adr = sony_toc->tracks[track_idx].address;
1455             loc_entry.cdte_ctrl = sony_toc->tracks[track_idx].control;
1456             msf_val = sony_toc->tracks[track_idx].track_start_msf;
1457          }
1458          
1459          /* Logical buffer address or MSF format requested? */
1460          if (loc_entry.cdte_format == CDROM_LBA)
1461          {
1462             loc_entry.cdte_addr.lba = msf_to_log(msf_val);
1463          }
1464          else if (loc_entry.cdte_format == CDROM_MSF)
1465          {
1466             loc_entry.cdte_addr.msf.minute = bcd_to_int(*msf_val);
1467             loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val+1));
1468             loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val+2));
1469          }
1470          memcpy_tofs(entry, &loc_entry, sizeof(*entry));
1471       }
1472       return 0;
1473       break;
1474 
1475    case CDROMPLAYTRKIND:     /* Play a track.  This currently ignores index. */
1476       {
1477          struct cdrom_ti ti;
1478          int track_idx;
1479          
1480          sony_get_toc();
1481          if (!sony_toc_read)
1482          {
1483             return -EIO;
1484          }
1485          
1486          verify_area(VERIFY_READ, (char *) arg, sizeof(ti));
1487          
1488          memcpy_fromfs(&ti, (char *) arg, sizeof(ti));
1489          if (   (ti.cdti_trk0 < sony_toc->first_track_num)
1490              || (ti.cdti_trk0 > sony_toc->last_track_num)
1491              || (ti.cdti_trk1 < ti.cdti_trk0))
1492          {
1493             return -EINVAL;
1494          }
1495          
1496          track_idx = find_track(int_to_bcd(ti.cdti_trk0));
1497          if (track_idx < 0)
1498          {
1499             return -EINVAL;
1500          }
1501          params[1] = sony_toc->tracks[track_idx].track_start_msf[0];
1502          params[2] = sony_toc->tracks[track_idx].track_start_msf[1];
1503          params[3] = sony_toc->tracks[track_idx].track_start_msf[2];
1504          
1505          /*
1506           * If we want to stop after the last track, use the lead-out
1507           * MSF to do that.
1508           */
1509          if (ti.cdti_trk1 >= bcd_to_int(sony_toc->last_track_num))
1510          {
1511             log_to_msf(msf_to_log(sony_toc->lead_out_start_msf)-1,
1512                        &(params[4]));
1513          }
1514          else
1515          {
1516             track_idx = find_track(int_to_bcd(ti.cdti_trk1+1));
1517             if (track_idx < 0)
1518             {
1519                return -EINVAL;
1520             }
1521             log_to_msf(msf_to_log(sony_toc->tracks[track_idx].track_start_msf)-1,
1522                        &(params[4]));
1523          }
1524          params[0] = 0x03;
1525          
1526          do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
1527          
1528          do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size);
1529          if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1530          {
1531             printk("Params: %x %x %x %x %x %x %x\n", params[0], params[1],
1532                    params[2], params[3], params[4], params[5], params[6]);
1533             printk("Sony CDROM error 0x%2.2x (CDROMPLAYTRKIND\n", res_reg[1]);
1534             return -EIO;
1535          }
1536          
1537          /* Save the final position for pauses and resumes */
1538          final_pos_msf[0] = params[4];
1539          final_pos_msf[1] = params[5];
1540          final_pos_msf[2] = params[6];
1541          sony_audio_status = CDROM_AUDIO_PLAY;
1542          return 0;
1543       }
1544      
1545    case CDROMSUBCHNL:   /* Get subchannel info */
1546       return sony_get_subchnl_info(arg);
1547 
1548    case CDROMVOLCTRL:   /* Volume control.  What volume does this change, anyway? */
1549       {
1550          struct cdrom_volctrl volctrl;
1551          
1552          verify_area(VERIFY_READ, (char *) arg, sizeof(volctrl));
1553          
1554          memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
1555          params[0] = SONY_SD_AUDIO_VOLUME;
1556          params[1] = volctrl.channel0;
1557          params[2] = volctrl.channel1;
1558          do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, params, 3, res_reg, &res_size);
1559          if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1560          {
1561             printk("Sony CDROM error 0x%2.2x (CDROMVOLCTRL)\n", res_reg[1]);
1562             return -EIO;
1563          }
1564       }
1565       return 0;
1566 
1567    case CDROMEJECT:     /* Eject the drive */
1568       do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, &res_size);
1569       do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
1570 
1571       sony_audio_status = CDROM_AUDIO_INVALID;
1572       do_sony_cd_cmd(SONY_EJECT_CMD, NULL, 0, res_reg, &res_size);
1573       if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1574       {
1575          printk("Sony CDROM error 0x%2.2x (CDROMEJECT)\n", res_reg[1]);
1576          return -EIO;
1577       }
1578       return 0;
1579       break;
1580      
1581    default:
1582       return -EINVAL;
1583    }
1584 }
1585 
1586 
1587 /*
1588  * Open the drive for operations.  Spin the drive up and read the table of
1589  * contents if these have not already been done.
1590  */
1591 static int
1592 scd_open(struct inode *inode,
1593          struct file *filp)
1594 {
1595    unsigned char res_reg[2];
1596    unsigned int res_size;
1597    int num_spin_ups;
1598 
1599 
1600    if (!sony_spun_up)
1601    {
1602       num_spin_ups = 0;
1603 
1604 respinup_on_open:
1605       do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
1606 
1607       /* The drive sometimes returns error 0.  I don't know why, but ignore
1608          it.  It seems to mean the drive has already done the operation. */
1609       if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0)))
1610       {
1611          printk("Sony CDROM error 0x%2.2x (scd_open, spin up)\n", res_reg[1]);
1612          return -EIO;
1613       }
1614       
1615       do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size);
1616 
1617       /* The drive sometimes returns error 0.  I don't know why, but ignore
1618          it.  It seems to mean the drive has already done the operation. */
1619       if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0)))
1620       {
1621          /* If the drive is already playing, its ok.  */
1622          if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR) || (res_reg[1] == 0))
1623          {
1624             goto drive_spinning;
1625          }
1626 
1627          /* If the drive says it is not spun up (even though we just did it!)
1628             then retry the operation at least a few times. */
1629          if (   (res_reg[1] == SONY_NOT_SPIN_ERR)
1630              && (num_spin_ups < MAX_CDU31A_RETRIES))
1631          {
1632             num_spin_ups++;
1633             goto respinup_on_open;
1634          }
1635 
1636          printk("Sony CDROM error 0x%2.2x (scd_open, read toc)\n", res_reg[1]);
1637          do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
1638          
1639          return -EIO;
1640       }
1641 
1642       sony_get_toc();
1643       if (!sony_toc_read)
1644       {
1645          do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
1646          return -EIO;
1647       }
1648 
1649       sony_spun_up = 1;
1650    }
1651 
1652 drive_spinning:
1653 
1654    if (inode)
1655    {
1656       check_disk_change(inode->i_rdev);
1657    }
1658 
1659    sony_usage++;
1660 
1661    return 0;
1662 }
1663 
1664 
1665 /*
1666  * Close the drive.  Spin it down if no task is using it.  The spin
1667  * down will fail if playing audio, so audio play is OK.
1668  */
1669 static void
1670 scd_release(struct inode *inode,
1671          struct file *filp)
1672 {
1673    unsigned char res_reg[2];
1674    unsigned int  res_size;
1675 
1676 
1677    if (sony_usage > 0)
1678    {
1679       sony_usage--;
1680    }
1681    if (sony_usage == 0)
1682    {
1683       sync_dev(inode->i_rdev);
1684       do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
1685 
1686       sony_spun_up = 0;
1687    }
1688 }
1689 
1690 
1691 static struct file_operations scd_fops = {
1692    NULL,                   /* lseek - default */
1693    block_read,             /* read - general block-dev read */
1694    block_write,            /* write - general block-dev write */
1695    NULL,                   /* readdir - bad */
1696    NULL,                   /* select */
1697    scd_ioctl,              /* ioctl */
1698    NULL,                   /* mmap */
1699    scd_open,               /* open */
1700    scd_release,            /* release */
1701    NULL                    /* fsync */
1702 };
1703 
1704 
1705 /* The different types of disc loading mechanisms supported */
1706 static char *load_mech[] = { "caddy", "tray", "pop-up", "unknown" };
1707 
1708 /* Read-ahead buffer sizes for different drives.  These are just arbitrary
1709    values, I don't know what is really optimum. */
1710 static unsigned int mem_size[] = { 16384, 16384, 16384, 2048 };
1711 
1712 void
1713 get_drive_configuration(unsigned short base_io,
1714                         unsigned char res_reg[],
1715                         unsigned int *res_size)
1716 {
1717    int retry_count;
1718 
1719 
1720    /* Set the base address */
1721    sony_cd_base_io = base_io;
1722 
1723    /* Set up all the register locations */
1724    sony_cd_cmd_reg = sony_cd_base_io + SONY_CMD_REG_OFFSET;
1725    sony_cd_param_reg = sony_cd_base_io + SONY_PARAM_REG_OFFSET;
1726    sony_cd_write_reg = sony_cd_base_io + SONY_WRITE_REG_OFFSET;
1727    sony_cd_control_reg = sony_cd_base_io + SONY_CONTROL_REG_OFFSET;
1728    sony_cd_status_reg = sony_cd_base_io + SONY_STATUS_REG_OFFSET;
1729    sony_cd_result_reg = sony_cd_base_io + SONY_RESULT_REG_OFFSET;
1730    sony_cd_read_reg = sony_cd_base_io + SONY_READ_REG_OFFSET;
1731    sony_cd_fifost_reg = sony_cd_base_io + SONY_FIFOST_REG_OFFSET;
1732 
1733    /*
1734     * Check to see if anything exists at the status register location.
1735     * I don't know if this is a good way to check, but it seems to work
1736     * ok for me.
1737     */
1738    if (read_status_register() != 0xff)
1739    {
1740       /*
1741        * Reset the drive and wait for attention from it (to say its reset).
1742        * If you don't wait, the next operation will probably fail.
1743        */
1744       reset_drive();
1745       retry_count = jiffies + SONY_RESET_TIMEOUT;
1746       while ((retry_count > jiffies) && (!is_attention()))
1747       {
1748          sony_sleep();
1749       }
1750 
1751       /* If attention is never seen probably not a CDU31a present */
1752       if (!is_attention())
1753       {
1754          res_reg[0] = 0x20;
1755          return;
1756       }
1757 
1758       /*
1759        * Get the drive configuration.
1760        */
1761       do_sony_cd_cmd(SONY_REQ_DRIVE_CONFIG_CMD,
1762                      NULL,
1763                      0,
1764                      (unsigned char *) res_reg,
1765                      res_size);
1766       return;
1767    }
1768 
1769    /* Return an error */
1770    res_reg[0] = 0x20;
1771 }
1772 
1773 
1774 /*
1775  * Initialize the driver.
1776  */
1777 unsigned long
1778 cdu31a_init(unsigned long mem_start, unsigned long mem_end)
1779 {
1780    struct s_sony_drive_config drive_config;
1781    unsigned int res_size;
1782    int i;
1783    int drive_found;
1784 
1785 
1786    /*
1787     * According to Alex Freed (freed@europa.orion.adobe.com), this is
1788     * required for the Fusion CD-16 package.  If the sound driver is
1789     * loaded, it should work fine, but just in case...
1790     *
1791     * The following turn on the CD-ROM interface for a Fusion CD-16.
1792     */
1793    outb(0xbc, 0x9a01);
1794    outb(0xe2, 0x9a01);
1795 
1796    i = 0;
1797    drive_found = 0;
1798    while (   (cdu31a_addresses[i] != 0)
1799           && (!drive_found))
1800    {
1801       if (check_region(cdu31a_addresses[i], 4)) {
1802           i++;
1803           continue;
1804       }
1805       get_drive_configuration(cdu31a_addresses[i],
1806                                drive_config.exec_status,
1807                                &res_size);
1808       if ((res_size > 2) && ((drive_config.exec_status[0] & 0x20) == 0x00))
1809       {
1810          drive_found = 1;
1811          snarf_region(cdu31a_addresses[i], 4);
1812 
1813          if (register_blkdev(MAJOR_NR,"cdu31a",&scd_fops))
1814          {
1815             printk("Unable to get major %d for CDU-31a\n", MAJOR_NR);
1816             return mem_start;
1817          }
1818 
1819          sony_buffer_size = mem_size[SONY_HWC_GET_BUF_MEM_SIZE(drive_config)];
1820          sony_buffer_sectors = sony_buffer_size / 2048;
1821 
1822          printk("Sony I/F CDROM : %8.8s %16.16s %8.8s with %s load mechanism\n",
1823                 drive_config.vendor_id,
1824                 drive_config.product_id,
1825                 drive_config.product_rev_level,
1826                 load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]);
1827          printk("  using %d byte buffer", sony_buffer_size);
1828          if (SONY_HWC_AUDIO_PLAYBACK(drive_config))
1829          {
1830             printk(", capable of audio playback");
1831          }
1832          printk("\n");
1833 
1834          set_drive_params();
1835 
1836          blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1837          read_ahead[MAJOR_NR] = 8;               /* 8 sector (4kB) read-ahead */
1838 
1839          sony_toc = (struct s_sony_toc *) mem_start;
1840          mem_start += sizeof(*sony_toc);
1841          last_sony_subcode = (struct s_sony_subcode *) mem_start;
1842          mem_start += sizeof(*last_sony_subcode);
1843          sony_buffer = (unsigned char *) mem_start;
1844          mem_start += sony_buffer_size;
1845       }
1846 
1847       i++;
1848    }
1849    
1850    return mem_start;
1851 }
1852 
1853 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -