* @internal * @brief Allocate a unit number * * On entry, @p *unitp is the desired unit number (or @c -1 if any * will do). The allocated unit number is returned in @p *unitp. * @param dc the devclass to allocate from * @param unitp points at the location for the allocated unit * number * * @retval 0 success * @retval EEXIST the requested unit number is already allocated * @retval
| 1611 | * @retval ENOMEM memory allocation failure |
| 1612 | */ |
| 1613 | static int |
| 1614 | devclass_alloc_unit(devclass_t dc, device_t dev, int *unitp) |
| 1615 | { |
| 1616 | const char *s; |
| 1617 | int unit = *unitp; |
| 1618 | |
| 1619 | PDEBUG(("unit %d in devclass %s", unit, DEVCLANAME(dc))); |
| 1620 | |
| 1621 | /* Ask the parent bus if it wants to wire this device. */ |
| 1622 | if (unit == -1) |
| 1623 | BUS_HINT_DEVICE_UNIT(device_get_parent(dev), dev, dc->name, |
| 1624 | &unit); |
| 1625 | |
| 1626 | /* If we were given a wired unit number, check for existing device */ |
| 1627 | /* XXX imp XXX */ |
| 1628 | if (unit != -1) { |
| 1629 | if (unit >= 0 && unit < dc->maxunit && |
| 1630 | dc->devices[unit] != NULL) { |
| 1631 | if (bootverbose) |
| 1632 | printf("%s: %s%d already exists; skipping it\n", |
| 1633 | dc->name, dc->name, *unitp); |
| 1634 | return (EEXIST); |
| 1635 | } |
| 1636 | } else { |
| 1637 | /* Unwired device, find the next available slot for it */ |
| 1638 | unit = 0; |
| 1639 | for (unit = 0;; unit++) { |
| 1640 | /* If there is an "at" hint for a unit then skip it. */ |
| 1641 | if (resource_string_value(dc->name, unit, "at", &s) == |
| 1642 | 0) |
| 1643 | continue; |
| 1644 | |
| 1645 | /* If this device slot is already in use, skip it. */ |
| 1646 | if (unit < dc->maxunit && dc->devices[unit] != NULL) |
| 1647 | continue; |
| 1648 | |
| 1649 | break; |
| 1650 | } |
| 1651 | } |
| 1652 | |
| 1653 | /* |
| 1654 | * We've selected a unit beyond the length of the table, so let's |
| 1655 | * extend the table to make room for all units up to and including |
| 1656 | * this one. |
| 1657 | */ |
| 1658 | if (unit >= dc->maxunit) { |
| 1659 | device_t *newlist, *oldlist; |
| 1660 | int newsize; |
| 1661 | |
| 1662 | oldlist = dc->devices; |
| 1663 | newsize = roundup((unit + 1), |
| 1664 | MAX(1, MINALLOCSIZE / sizeof(device_t))); |
| 1665 | newlist = malloc(sizeof(device_t) * newsize, M_BUS, M_NOWAIT); |
| 1666 | if (!newlist) |
| 1667 | return (ENOMEM); |
| 1668 | if (oldlist != NULL) |
| 1669 | bcopy(oldlist, newlist, sizeof(device_t) * dc->maxunit); |
| 1670 | bzero(newlist + dc->maxunit, |
no test coverage detected