VirtualBox

Ignore:
Timestamp:
Mar 13, 2009 5:42:43 PM (16 years ago)
Author:
vboxsync
Message:

Additions/linux/vboxadd: refactored the module initialisation code

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/linux/module/vboxmod.c

    r16315 r17853  
    901901}
    902902
    903 /** strategy handlers (file operations) */
    904 static struct file_operations vbox_fops =
     903/** file operations for the vboxadd device */
     904static struct file_operations vboxadd_fops =
    905905{
    906906    .owner   = THIS_MODULE,
     
    914914};
    915915
    916 static struct miscdevice gMiscDevice =
     916/** Miscellaneous device allocation for vboxadd */
     917static struct miscdevice gMiscVBoxAdd =
    917918{
    918919    minor:      MISC_DYNAMIC_MINOR,
    919     name:       "vboxadd",
    920     fops:       &vbox_fops
     920    name:       VBOXADD_NAME,
     921    fops:       &vboxadd_fops
    921922};
    922923
     
    11691170static __init int init(void)
    11701171{
    1171     int err;
    1172     int rcVBox;
     1172    int rc = 0, rcVBox = VINF_SUCCESS;
     1173    bool haveVBoxAdd = false, haveGuestLib = false;
    11731174    struct pci_dev *pcidev = NULL;
    1174     VMMDevReportGuestInfo *infoReq = NULL;
    1175 
    1176     if (vboxadd_cmc_init ())
    1177     {
    1178         printk (KERN_ERR "vboxadd: could not init cmc.\n");
    1179         return -ENODEV;
    1180     }
    1181 
    1182     /*
    1183      * Detect PCI device
    1184      */
    1185     pcidev = PCI_DEV_GET(VMMDEV_VENDORID, VMMDEV_DEVICEID, pcidev);
    1186     if (!pcidev)
    1187     {
    1188         printk(KERN_ERR "vboxadd: VirtualBox PCI device not found.\n");
    1189         return -ENODEV;
    1190     }
    1191 
    1192     err = pci_enable_device (pcidev);
    1193     if (err)
    1194     {
    1195         Log(("vboxadd: could not enable device: %d\n", err));
    1196         PCI_DEV_PUT(pcidev);
    1197         return -ENODEV;
    1198     }
    1199 
    1200     LogRel(("Starting VirtualBox version %s Guest Additions\n",
    1201             VBOX_VERSION_STRING));
    1202     /* register a character device */
    1203     if (vbox_major > 0)
    1204     {
    1205         err = register_chrdev(vbox_major, "vboxadd", &vbox_fops);
    1206         if (err < 0 || (vbox_major & err) || (!vbox_major && !err))
    1207         {
    1208             LogRelFunc(("register_chrdev failed: vbox_major: %d, err = %d\n",
    1209                         vbox_major, err));
    1210             PCI_DEV_PUT(pcidev);
    1211             return -ENODEV;
    1212         }
    1213         /* if no major code was set, take the return value */
    1214         if (!vbox_major)
    1215             vbox_major = err;
    1216     }
    1217     else
    1218     {
    1219         err = misc_register(&gMiscDevice);
    1220         if (err)
    1221         {
    1222             LogRelFunc(("misc_register failed (rc=%d)\n", err));
    1223             return -ENODEV;
    1224         }
    1225     }
     1175
     1176    rcVBox = vboxadd_cmc_init();
     1177    if (RT_FAILURE(rcVBox))
     1178    {
     1179        printk (KERN_ERR "vboxadd: could not init cmc, VBox error code %d.\n", rcVBox);
     1180        rc = -RTErrConvertToErrno(rcVBox);
     1181    }
     1182
     1183    /* Detect PCI device */
     1184    if (!rc)
     1185    {
     1186        pcidev = PCI_DEV_GET(VMMDEV_VENDORID, VMMDEV_DEVICEID, pcidev);
     1187        if (!pcidev)
     1188        {
     1189            printk(KERN_ERR "vboxadd: VirtualBox Guest PCI device not found.\n");
     1190            rc = -ENODEV;
     1191        }
     1192    }
     1193
     1194    if (!rc)
     1195    {
     1196        rc = pci_enable_device (pcidev);
     1197        if (rc)
     1198            LogRel(("vboxadd: could not enable device: %d\n", rc));
     1199    }
     1200    if (rc)
     1201        LogRel(("Starting VirtualBox version %s Guest Additions\n",
     1202                VBOX_VERSION_STRING));
     1203
     1204    /* Register vboxadd */
     1205    if (!rc && vbox_major > 0)  /* Register as a character device in this case */
     1206    {
     1207        rc = register_chrdev(vbox_major, VBOXADD_NAME, &vboxadd_fops);
     1208        if (rc)  /* As we pass a non-zero major, rc should be zero on success. */
     1209            LogRel(("vboxadd: register_chrdev failed: vbox_major: %d, err = %d\n",
     1210                        vbox_major, rc));
     1211    }
     1212    else if (!rc)  /* Register as a miscellaneous device otherwise */
     1213    {
     1214        rc = misc_register(&gMiscVBoxAdd);
     1215        if (rc)
     1216            LogRel(("vboxadd: misc_register failed for %s (rc=%d)\n",
     1217                    VBOXADD_NAME, rc));
     1218    }
     1219    if (!rc)
     1220        haveVBoxAdd = true;
    12261221
    12271222    /* allocate and initialize device extension */
    1228     vboxDev = kmalloc(sizeof(*vboxDev), GFP_KERNEL);
    1229     if (!vboxDev)
    1230     {
    1231         LogRelFunc(("cannot allocate device!\n"));
    1232         err = -ENOMEM;
    1233         goto fail;
    1234     }
    1235     memset(vboxDev, 0, sizeof(*vboxDev));
    1236     snprintf(vboxDev->name, sizeof(vboxDev->name), "vboxadd");
    1237 
    1238     /* get the IO port region */
    1239     vboxDev->io_port = pci_resource_start(pcidev, 0);
    1240 
    1241     /* get the memory region */
    1242     vboxDev->vmmdevmem = pci_resource_start(pcidev, 1);
    1243     vboxDev->vmmdevmem_size = pci_resource_len(pcidev, 1);
    1244 
    1245     /* all resources found? */
    1246     if (!vboxDev->io_port || !vboxDev->vmmdevmem || !vboxDev->vmmdevmem_size)
    1247     {
    1248         LogRelFunc(("did not find expected hardware resources!\n"));
    1249         err = -ENXIO;
    1250         goto fail;
     1223    if (!rc)
     1224    {
     1225        vboxDev = kmalloc(sizeof(*vboxDev), GFP_KERNEL);
     1226        if (vboxDev)
     1227            memset(vboxDev, 0, sizeof(*vboxDev));
     1228        else
     1229        {
     1230            LogRel(("vboxadd: could not allocate private device structure\n"));
     1231            rc = -ENOMEM;
     1232        }
     1233    }
     1234
     1235    if (!rc)
     1236    {
     1237        /* get the IO port region */
     1238        vboxDev->io_port = pci_resource_start(pcidev, 0);
     1239
     1240        /* get the memory region */
     1241        vboxDev->vmmdevmem = pci_resource_start(pcidev, 1);
     1242        vboxDev->vmmdevmem_size = pci_resource_len(pcidev, 1);
     1243
     1244        /* all resources found? */
     1245        if (!vboxDev->io_port || !vboxDev->vmmdevmem || !vboxDev->vmmdevmem_size)
     1246        {
     1247            LogRel(("vboxadd: did not find expected hardware resources\n"));
     1248            rc = -ENXIO;
     1249        }
    12511250    }
    12521251
    12531252    /* request ownership of adapter memory */
    1254     if (request_mem_region(vboxDev->vmmdevmem, vboxDev->vmmdevmem_size, "vboxadd") == 0)
    1255     {
    1256         LogRelFunc(("failed to request adapter memory!\n"));
    1257         err = -ENXIO;
    1258         goto fail;
     1253    if (!rc && !request_mem_region(vboxDev->vmmdevmem, vboxDev->vmmdevmem_size,
     1254                                   VBOXADD_NAME))
     1255    {
     1256        LogRel(("vboxadd: failed to obtain adapter memory\n"));
     1257        rc = -EBUSY;
    12591258    }
    12601259
    12611260    /* map adapter memory into kernel address space and check version */
    1262     vboxDev->pVMMDevMemory = (VMMDevMemory *) ioremap(vboxDev->vmmdevmem,
     1261    if (!rc)
     1262    {
     1263        vboxDev->pVMMDevMemory = (VMMDevMemory *) ioremap(vboxDev->vmmdevmem,
    12631264                                                      vboxDev->vmmdevmem_size);
    1264     if (!vboxDev->pVMMDevMemory)
    1265     {
    1266         LogRelFunc(("ioremap failed\n"));
    1267         err = -ENOMEM;
    1268         goto fail;
    1269     }
    1270 
    1271     if (vboxDev->pVMMDevMemory->u32Version != VMMDEV_MEMORY_VERSION)
    1272     {
    1273         LogRelFunc(("invalid VMM device memory version! (got 0x%x, expected 0x%x)\n",
    1274                     vboxDev->pVMMDevMemory->u32Version, VMMDEV_MEMORY_VERSION));
    1275         err = -ENXIO;
    1276         goto fail;
    1277     }
    1278 
    1279     /* initialize VBGL subsystem */
    1280     rcVBox = VbglInit(vboxDev->io_port, vboxDev->pVMMDevMemory);
    1281     if (RT_FAILURE(rcVBox))
    1282     {
    1283         LogRelFunc(("could not initialize VBGL subsystem! rc = %Rrc\n", rcVBox));
    1284         err = -ENXIO;
    1285         goto fail;
    1286     }
     1265        if (!vboxDev->pVMMDevMemory)
     1266        {
     1267            LogRel(("vboxadd: ioremap failed\n"));
     1268            rc = -ENOMEM;
     1269        }
     1270    }
     1271
     1272    if (!rc && (vboxDev->pVMMDevMemory->u32Version != VMMDEV_MEMORY_VERSION))
     1273    {
     1274        LogRel(("vboxadd: invalid VMM device memory version! (got 0x%x, expected 0x%x)\n",
     1275                   vboxDev->pVMMDevMemory->u32Version, VMMDEV_MEMORY_VERSION));
     1276        rc = -ENXIO;
     1277    }
     1278
     1279    /* initialize ring 0 guest library */
     1280    if (!rc)
     1281    {
     1282        rcVBox = VbglInit(vboxDev->io_port, vboxDev->pVMMDevMemory);
     1283        if (RT_FAILURE(rcVBox))
     1284        {
     1285            LogRel(("vboxadd: could not initialize VBGL subsystem: %Rrc\n",
     1286                    rcVBox));
     1287            rc = -RTErrConvertToErrno(rcVBox);
     1288        }
     1289    }
     1290    if (!rc)
     1291        haveGuestLib = true;
    12871292
    12881293    /* report guest information to host, this must be done as the very first request */
    1289     rcVBox = VbglGRAlloc((VMMDevRequestHeader**)&infoReq,
    1290                          sizeof(VMMDevReportGuestInfo), VMMDevReq_ReportGuestInfo);
    1291     if (RT_FAILURE(rcVBox))
    1292     {
    1293         LogRelFunc(("could not allocate request structure! rc = %Rrc\n", rcVBox));
    1294         err = -ENOMEM;
    1295         goto fail;
    1296     }
    1297 
    1298     /* report guest version to host, the VMMDev requires that to be done first */
    1299     infoReq->guestInfo.additionsVersion = VMMDEV_VERSION;
     1294    if (!rc)
     1295    {
     1296        VMMDevReportGuestInfo *infoReq = NULL;
     1297
     1298        rcVBox = VbglGRAlloc((VMMDevRequestHeader**)&infoReq,
     1299                             sizeof(VMMDevReportGuestInfo), VMMDevReq_ReportGuestInfo);
     1300        if (RT_FAILURE(rcVBox))
     1301        {
     1302            LogRel(("vboxadd: could not allocate request structure: %Rrc\n", rcVBox));
     1303            rc = -RTErrConvertToErrno(rcVBox);
     1304        }
     1305        /* report guest version to host, the VMMDev requires that to be done
     1306         * before any other VMMDev operations. */
     1307        if (infoReq)
     1308        {
     1309            infoReq->guestInfo.additionsVersion = VMMDEV_VERSION;
    13001310#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0)
    1301     infoReq->guestInfo.osType = VBOXOSTYPE_Linux26;
     1311            infoReq->guestInfo.osType = VBOXOSTYPE_Linux26;
    13021312#else
    1303     infoReq->guestInfo.osType = VBOXOSTYPE_Linux24;
     1313            infoReq->guestInfo.osType = VBOXOSTYPE_Linux24;
    13041314#endif
    1305     rcVBox = VbglGRPerform(&infoReq->header);
    1306     if (RT_FAILURE(rcVBox) || RT_FAILURE(infoReq->header.rc))
    1307     {
    1308         LogRelFunc(("error reporting guest info to host! rc = %Rrc, header.rc = %Rrc\n",
    1309                     rcVBox, infoReq->header.rc));
    1310         VbglGRFree(&infoReq->header);
    1311         err = -ENXIO;
    1312         goto fail;
    1313     }
    1314     VbglGRFree(&infoReq->header);
     1315            rcVBox = VbglGRPerform(&infoReq->header);
     1316        }
     1317        if (infoReq && (RT_FAILURE(rcVBox) || RT_FAILURE(infoReq->header.rc)))
     1318        {
     1319            LogRel(("vboxadd: error reporting guest information to host: %Rrc, header: %Rrc\n",
     1320                        rcVBox, infoReq->header.rc));
     1321            rc = RT_FAILURE(rcVBox) ? -RTErrConvertToErrno(rcVBox)
     1322                                    : -RTErrConvertToErrno(infoReq->header.rc);
     1323        }
     1324        if (infoReq)
     1325            VbglGRFree(&infoReq->header);
     1326    }
    13151327
    13161328    /* Unset the graphics capability until/unless X is loaded. */
    13171329    /** @todo check the error code once we bump the additions version.
    13181330              For now we ignore it for compatibility with older hosts. */
     1331    if (!rc)
    13191332    {
    13201333        VMMDevReqGuestCapabilities2 *vmmreqGuestCaps;
    1321 
    13221334
    13231335        rcVBox = VbglGRAlloc((VMMDevRequestHeader**)&vmmreqGuestCaps,
     
    13261338        if (RT_FAILURE(rcVBox))
    13271339        {
    1328             LogRelFunc(("could not allocate request structure! rc = %Rrc\n", rcVBox));
    1329             err = -ENOMEM;
    1330             goto fail;
    1331         }
    1332         vmmreqGuestCaps->u32OrMask = 0;
    1333         vmmreqGuestCaps->u32NotMask = VMMDEV_GUEST_SUPPORTS_GRAPHICS;
    1334         rcVBox = VbglGRPerform(&vmmreqGuestCaps->header);
    1335         VbglGRFree(&vmmreqGuestCaps->header);
     1340            LogRel(("vboxadd: could not allocate request structure: %Rrc\n",
     1341                    rcVBox));
     1342            rc = -RTErrConvertToErrno(rcVBox);
     1343        }
     1344        else
     1345        {
     1346            vmmreqGuestCaps->u32OrMask = 0;
     1347            vmmreqGuestCaps->u32NotMask = VMMDEV_GUEST_SUPPORTS_GRAPHICS;
     1348            rcVBox = VbglGRPerform(&vmmreqGuestCaps->header);
     1349            if (RT_FAILURE(rcVBox))
     1350            {
     1351                LogRel(("vboxadd: could not allocate request structure: %Rrc\n",
     1352                        rcVBox));
     1353                rc = -RTErrConvertToErrno(rcVBox);
     1354            }
     1355            VbglGRFree(&vmmreqGuestCaps->header);
     1356        }
     1357    }
     1358
     1359    /* perform hypervisor address space reservation */
     1360    if (!rc && vboxadd_reserve_hypervisor())
     1361    {
     1362        /* we just ignore the error, no address window reservation, non fatal */
     1363    }
     1364
     1365    /* allocate a VMM request structure for use in the ISR */
     1366    if (!rc)
     1367    {
     1368        rcVBox = VbglGRAlloc((VMMDevRequestHeader**)&vboxDev->irqAckRequest,
     1369                             sizeof(VMMDevEvents), VMMDevReq_AcknowledgeEvents);
    13361370        if (RT_FAILURE(rcVBox))
    13371371        {
    1338             err = -ENXIO;
    1339             goto fail;
    1340         }
    1341     }
    1342 
    1343     /* perform hypervisor address space reservation */
    1344     if (vboxadd_reserve_hypervisor())
    1345     {
    1346         /* we just ignore the error, no address window reservation, non fatal */
    1347     }
    1348 
    1349     /* allocate a VMM request structure for use in the ISR */
    1350     rcVBox = VbglGRAlloc((VMMDevRequestHeader**)&vboxDev->irqAckRequest,
    1351                          sizeof(VMMDevEvents), VMMDevReq_AcknowledgeEvents);
    1352     if (RT_FAILURE(rcVBox))
    1353     {
    1354         LogRelFunc(("could not allocate request structure! rc = %Rrc\n", rcVBox));
    1355         err = -ENOMEM;
    1356         goto fail;
     1372            LogRel(("vboxadd: could not allocate request structure: %Rrc\n",
     1373                    rcVBox));
     1374            rc = -RTErrConvertToErrno(rcVBox);
     1375        }
    13571376    }
    13581377
    13591378    /* get ISR */
    1360     err = request_irq(pcidev->irq, vboxadd_irq_handler,
     1379    if (!rc)
     1380    {
     1381        rc = request_irq(pcidev->irq, vboxadd_irq_handler,
    13611382#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
    1362                       IRQF_SHARED,
     1383                          IRQF_SHARED,
    13631384#else
    1364                       SA_SHIRQ,
     1385                          SA_SHIRQ,
    13651386#endif
    1366                       "vboxadd", vboxDev);
    1367     if (err)
    1368     {
    1369         LogRelFunc(("could not request IRQ %d, err: %d\n", pcidev->irq, err));
    1370         goto fail;
    1371     }
    1372     vboxDev->irq = pcidev->irq;
    1373 
    1374     init_waitqueue_head (&vboxDev->eventq);
    1375 
    1376     {
     1387                          VBOXADD_NAME, vboxDev);
     1388        if (rc)
     1389            LogRel(("vboxadd: could not request IRQ %d, err: %d\n", pcidev->irq, rc));
     1390        else
     1391            vboxDev->irq = pcidev->irq;
     1392    }
     1393
     1394    if (!rc)
     1395    {
     1396        VBoxGuestFilterMaskInfo info;
     1397
     1398        init_waitqueue_head (&vboxDev->eventq);
    13771399        /* Register for notification when the host absolute pointer position
    13781400         * changes. */
    1379         VBoxGuestFilterMaskInfo info;
    13801401        info.u32OrMask = VMMDEV_EVENT_MOUSE_POSITION_CHANGED;
    13811402        info.u32NotMask = 0;
     
    13831404        if (!RT_SUCCESS(rcVBox))
    13841405        {
    1385             LogRelFunc(("failed to register for VMMDEV_EVENT_MOUSE_POSITION_CHANGED events\n"));
    1386             err = -RTErrConvertToErrno(rcVBox);
    1387             goto fail;
    1388         }
    1389     }
    1390 
    1391     /* some useful information for the user but don't show this on the console */
    1392     LogRel(("VirtualBox device settings: major %d, IRQ %d, "
     1406            LogRel(("vboxadd: failed to register for VMMDEV_EVENT_MOUSE_POSITION_CHANGED events: %Rrc\n",
     1407                    rcVBox));
     1408            rc = -RTErrConvertToErrno(rcVBox);
     1409        }
     1410    }
     1411
     1412    if (!rc)
     1413    {
     1414        /* some useful information for the user but don't show this on the console */
     1415        LogRel(("VirtualBox device settings: major %d, IRQ %d, "
    13931416                "I/O port 0x%x, MMIO at 0x%x (size 0x%x), "
    13941417                "hypervisor window at 0x%p (size 0x%x)\n",
     
    13961419                vboxDev->vmmdevmem, vboxDev->vmmdevmem_size,
    13971420                vboxDev->hypervisorStart, vboxDev->hypervisorSize));
    1398     printk(KERN_DEBUG "vboxadd: Successfully loaded version "
    1399             VBOX_VERSION_STRING " (interface " xstr(VMMDEV_VERSION) ")\n");
    1400 
    1401     /* successful return */
    1402     PCI_DEV_PUT(pcidev);
    1403     return 0;
    1404 
    1405 fail:
    1406     PCI_DEV_PUT(pcidev);
    1407     free_resources();
     1421        printk(KERN_DEBUG "vboxadd: Successfully loaded version "
     1422                VBOX_VERSION_STRING " (interface " xstr(VMMDEV_VERSION) ")\n");
     1423    }
     1424    else  /* Clean up on failure */
     1425    {
     1426        if (haveGuestLib)
     1427            VbglTerminate();
     1428        if (vboxDev)
     1429            free_resources();
     1430        if (haveVBoxAdd && vbox_major > 0)
     1431            unregister_chrdev(vbox_major, VBOXADD_NAME);
     1432        else if (haveVBoxAdd)
     1433            misc_deregister(&gMiscVBoxAdd);
     1434    }
     1435    /* We always release this.  Presumably because we no longer need to do
     1436     * anything with the device structure. */
     1437    if (pcidev)
     1438        PCI_DEV_PUT(pcidev);
     1439    return rc;
     1440}
     1441
     1442/**
     1443 * Module termination
     1444 *
     1445 */
     1446static __exit void fini(void)
     1447{
    14081448    if (vbox_major > 0)
    1409         unregister_chrdev(vbox_major, "vboxadd");
     1449        unregister_chrdev(vbox_major, VBOXADD_NAME);
    14101450    else
    1411         misc_deregister(&gMiscDevice);
    1412     return err;
    1413 }
    1414 
    1415 /**
    1416  * Module termination
    1417  *
    1418  */
    1419 static __exit void fini(void)
    1420 {
    1421     if (vbox_major > 0)
    1422         unregister_chrdev(vbox_major, "vboxadd");
    1423     else
    1424         misc_deregister(&gMiscDevice);
     1451        misc_deregister(&gMiscVBoxAdd);
    14251452    free_resources();
    14261453    vboxadd_cmc_fini ();
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette