static int get_modem_info(struct async_struct *info, unsigned int *result) { mach_msg_type_number_t count; kern_return_t kr; unsigned long value, status = 0; count = TTY_MODEM_COUNT; kr = device_get_status(info->device_port, TTY_MODEM, (dev_status_t)&status, &count); if (kr != D_SUCCESS) return -EIO; value = 0; if (status & TM_RTS) value |= TIOCM_RTS; if (status & TM_DTR) value |= TIOCM_DTR; if (status & TM_CAR) value |= TIOCM_CAR; put_user(value, result); return 0; }
int set_promisc (char *dev_name, mach_port_t ether_port, int is_promisc) { #ifndef NET_FLAGS #define NET_FLAGS (('n'<<16) + 4) #endif int flags; int ret; size_t count; debug ("set_promisc is called, is_promisc: %d\n", is_promisc); count = 1; ret = device_get_status (ether_port, NET_FLAGS, (dev_status_t) &flags, &count); if (ret) { error (0, ret, "device_get_status"); return -1; } if (is_promisc) flags |= IFF_PROMISC; else flags &= ~IFF_PROMISC; ret = device_set_status(ether_port, NET_FLAGS, (dev_status_t) &flags, 1); if (ret) { error (0, ret, "device_set_status"); return -1; } return 0; }
static void serial_handle_oob_event(struct async_struct *info, mach_port_t device_port) { kern_return_t kr; mach_msg_type_number_t count; struct tty_out_of_band toob; count = TTY_OUT_OF_BAND_COUNT; kr = device_get_status(device_port, TTY_OUT_OF_BAND, (dev_status_t) &toob, &count); if (kr != D_SUCCESS) { MACH3_DEBUG(1, kr, ("serial_handle_oob_event(%d):device_get_status",kr )); return; } switch (toob.toob_event) { case TOOB_NO_EVENT: break; case TOOB_BREAK: serial_put_status_byte(info, TTY_BREAK); break; case TOOB_BAD_PARITY: serial_put_status_byte(info, TTY_PARITY); break; case TOOB_FLUSHED: break; case TOOB_CARRIER: if (toob.toob_arg) { info->flags |= ASYNC_DCD_PRESENT; wake_up_interruptible(&info->open_wait); } else { info->flags &= ~ASYNC_DCD_PRESENT; if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && (info->flags & ASYNC_CALLOUT_NOHUP))) { #ifdef SERIAL_DEBUG_OPEN printk("scheduling hangup..."); #endif queue_task_irq_off(&info->tqueue_hangup, &tq_scheduler); } } break; default: printk("serial_handle_oob_event: unknown event 0x%x\n", toob.toob_event); break; } return; }
static int set_modem_info(struct async_struct * info, unsigned int cmd, unsigned int *value) { int error; unsigned int arg; long result = 0, cur; mach_msg_type_number_t count; kern_return_t kr; error = verify_area(VERIFY_READ, value, sizeof(int)); if (error) return error; arg = get_user(value); if (arg & TIOCM_RTS) result |= TM_RTS; if (arg & TIOCM_DTR) result |= TM_DTR; count = TTY_MODEM_COUNT; kr = device_get_status(info->device_port, TTY_MODEM, (dev_status_t)&cur, &count); if (kr != D_SUCCESS) return -EIO; switch (cmd) { case TIOCMBIS: cur = cur | result; break; case TIOCMBIC: cur = cur & ~result; break; case TIOCMSET: cur = result; break; default: return -EINVAL; } kr = device_set_status(info->device_port, TTY_MODEM, (dev_status_t)&cur, TTY_MODEM_COUNT); if (kr != D_SUCCESS) return -EIO; return 0; }
/* * Retrieve the semaphore associated with an endpoint group. */ FLIPC_return_t FLIPC_epgroup_semaphore(FLIPC_epgroup_t epgroup_arg, semaphore_port_t *semaphore) { flipc_epgroup_t epgroup = epgroup_arg; kern_return_t kr; domain_lookup_t dl = domain_pointer_lookup(epgroup); flipc_comm_buffer_ctl_t cb_ctl; int dev_status[1]; unsigned int dev_status_count; if (!dl) /* No domain pointer means that we were passed a bad epgroup_arg. */ return FLIPC_INVALID_ARGUMENTS; cb_ctl = (flipc_comm_buffer_ctl_t) dl->comm_buffer_base; /* No point in checking if structure's enabled, as it might be disabled before we get out of the kernel. */ /* Get the semaphore. */ dev_status_count = 1; kr = device_get_status(dl->device_port, FLIPC_DEVICE_FLAVOR(usermsg_Get_Epgroup_Semaphore, (epgroup - FLIPC_EPGROUP_PTR(cb_ctl->epgroup.start))), dev_status, &dev_status_count); if (kr != KERN_SUCCESS) { switch (kr) { case D_INVALID_OPERATION: return FLIPC_INVALID_ARGUMENTS; case D_DEVICE_DOWN: return FLIPC_DOMAIN_NOT_INITIALIZED; default: return FLIPC_KERNEL_TRANSLATION_ERR; } } *semaphore = (semaphore_port_t) dev_status[0]; return FLIPC_SUCCESS; }
void setup_ethernet_device (char *name, struct device **device) { struct net_status netstat; size_t count; int net_address[2]; error_t err; struct ether_device *edev; struct device *dev; edev = calloc (1, sizeof (struct ether_device)); if (!edev) error (2, ENOMEM, "%s", name); edev->next = ether_dev; ether_dev = edev; *device = dev = &edev->dev; dev->name = strdup (name); /* Functions. These ones are the true "hardware layer" in Linux. */ dev->open = 0; /* We set up before calling dev_open. */ dev->stop = ethernet_stop; dev->hard_start_xmit = ethernet_xmit; dev->get_stats = ethernet_get_stats; dev->set_multicast_list = ethernet_set_multi; /* These are the ones set by drivers/net/net_init.c::ether_setup. */ dev->hard_header = eth_header; dev->rebuild_header = eth_rebuild_header; dev->hard_header_cache = eth_header_cache; dev->header_cache_update = eth_header_cache_update; dev->hard_header_parse = eth_header_parse; /* We can't do these two (and we never try anyway). */ /* dev->change_mtu = eth_change_mtu; */ /* dev->set_mac_address = eth_mac_addr; */ /* Some more fields */ dev->priv = edev; /* For reverse lookup. */ dev->type = ARPHRD_ETHER; dev->hard_header_len = ETH_HLEN; dev->addr_len = ETH_ALEN; memset (dev->broadcast, 0xff, ETH_ALEN); dev->flags = IFF_BROADCAST | IFF_MULTICAST; /* FIXME: Receive all multicast to fix IPv6, until we implement ethernet_set_multi. */ dev->flags |= IFF_ALLMULTI; dev->change_flags = ethernet_change_flags; dev_init_buffers (dev); ethernet_open (dev); /* Fetch hardware information */ count = NET_STATUS_COUNT; err = device_get_status (edev->ether_port, NET_STATUS, (dev_status_t) &netstat, &count); if (err) error (2, err, "%s: Cannot get device status", name); dev->mtu = netstat.max_packet_size - dev->hard_header_len; assert (netstat.header_format == HDR_ETHERNET); assert (netstat.header_size == ETH_HLEN); assert (netstat.address_size == ETH_ALEN); count = 2; assert (count * sizeof (int) >= ETH_ALEN); err = device_get_status (edev->ether_port, NET_ADDRESS, net_address, &count); if (err) error (2, err, "%s: Cannot get hardware Ethernet address", name); net_address[0] = ntohl (net_address[0]); net_address[1] = ntohl (net_address[1]); memcpy (dev->dev_addr, net_address, ETH_ALEN); /* That should be enough. */ /* This call adds the device to the `dev_base' chain, initializes its `ifindex' member (which matters!), and tells the protocol stacks about the device. */ err = - register_netdevice (dev); assert_perror (err); }
int machine_disk_get_params( kdev_t dev, mach_port_t device_port, struct hd_geometry *loc, boolean_t partition_only) { kern_return_t kr; struct disk_parms dp; #if 0 struct disklabel dl; #endif unsigned int count; unsigned char heads; unsigned char sectors; unsigned short cylinders; long start; switch ((int) MAJOR(dev)) { case SCSI_DISK_MAJOR: #if 0 count = sizeof (struct disklabel) / sizeof (int); kr = device_get_status(device_port, DIOCGDINFO, (dev_status_t) &dl, &count); if (kr != D_SUCCESS) { MACH3_DEBUG(2, kr, ("machine_get_disk_params(%s): " "device_get_status(0x%x, DIOCGDINFO)", kdevname(dev), device_port)); return -EINVAL; } heads = (unsigned char) dl.d_ntracks; sectors = (unsigned char) dl.d_nsectors; /* XXX */ cylinders = (unsigned short) dl.d_ncylinders; start = 0; /* XXX */ break; #endif case HD_MAJOR: case FLOPPY_MAJOR: count = sizeof (struct disk_parms) / sizeof (int); kr = device_get_status(device_port, OSFMACH3_V_GETPARMS, (dev_status_t) &dp, &count); if (kr != D_SUCCESS) { MACH3_DEBUG(2, kr, ("machine_get_disk_params(%s): " "device_get_status(0x%x, V_GETPARMS)", kdevname(dev), device_port)); return -EINVAL; } heads = dp.dp_dosheads; cylinders = dp.dp_doscyls; sectors = dp.dp_dossectors; if (partition_only) { #if 0 sectors = (dp.dp_pnumsec * dp.dp_secsiz) / 512; #endif start = (dp.dp_pstartsec * dp.dp_secsiz) / 512; } else { start = 0; } break; default: return -EINVAL; } #ifdef GENDISK_DEBUG if (gendisk_debug) { printk("machine_disk_get_params(dev=%s, part_only=%d): " "%d heads, %d cylinders, %d sectors, start at %ld\n", kdevname(dev), partition_only, heads, cylinders, sectors, start); } #endif /* GENDISK_DEBUG */ put_fs_byte(heads, (char *) &loc->heads); put_fs_byte(sectors, (char *) &loc->sectors); put_fs_word(cylinders, (short *) &loc->cylinders); put_fs_long(start, (long *) &loc->start); return 0; }
kern_return_t machine_disk_read_absolute( kdev_t dev, mach_port_t device_port, unsigned long recnum, char *data, unsigned long size) { kern_return_t kr; mach_msg_type_number_t count; int abs_sec; /* absolute sector to be read */ abs_sec = recnum; while (size > 0) { #ifdef GENDISK_DEBUG if (gendisk_debug) { printk("machine_disk_read_absolute(dev=%s, " "recnum=0x%lx, size=0x%lx): RDABS(0x%x,0x%x)\n", kdevname(dev), recnum, size, abs_sec, OSFMACH3_DEV_BSIZE); } #endif /* GENDISK_DEBUG */ /* * Tell the micro-kernel which sector to read. */ count = 1; kr = device_set_status(device_port, OSFMACH3_V_ABS, (dev_status_t) &abs_sec, count); if (kr != KERN_SUCCESS) { MACH3_DEBUG(1, kr, ("machine_disk_read_absolute(%s): " "device_set_status(0x%x, V_ABS, " "0x%x)", kdevname(dev), device_port, abs_sec)); return kr; } /* * Read the sector now. */ count = OSFMACH3_DEV_BSIZE / sizeof (int); server_thread_blocking(FALSE); kr = device_get_status(device_port, OSFMACH3_V_RDABS, (dev_status_t) data, &count); server_thread_unblocking(FALSE); if (kr != D_SUCCESS) { if (kr != D_INVALID_RECNUM && kr != D_INVALID_SIZE) { MACH3_DEBUG(1, kr, ("machine_disk_read_absolute(%s): " "device_get_status(0x%x, " "V_RDABS(0x%x,%d))", kdevname(dev), device_port, abs_sec, count)); } return kr; } if ((count * sizeof (int)) > size) break; size -= count * sizeof (int); data += count * sizeof (int); abs_sec++; } return D_SUCCESS; }
/* * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */ static void change_speed(struct async_struct *info) { unsigned cflag; int line; mach_port_t device_port; kern_return_t kr; struct tty_status ttstat; mach_msg_type_number_t ttstat_count; if (!info->tty || !info->tty->termios) return; cflag = info->tty->termios->c_cflag; line = MINOR(info->tty->device) - info->tty->driver.minor_start; device_port = info->device_port; ttstat_count = TTY_STATUS_COUNT; if (device_port != MACH_PORT_NULL) { kr = device_get_status(device_port, TTY_STATUS_NEW, (dev_status_t) &ttstat, &ttstat_count); if (kr != D_SUCCESS) { MACH3_DEBUG(1, kr, ("change_speed(dev 0x%x): " "device_get_status(TTY_STATUS_NEW)", info->tty->device)); return; } } /* Mach break handling is obsolete with "new" out-of-band. */ ttstat.tt_breakc = 0; ttstat.tt_flags &= ~(TF_ODDP | TF_EVENP | TF_LITOUT | TF_NOHANG | TF_8BIT | TF_READ | TF_HUPCLS | TF_OUT_OF_BAND | TF_INPCK | TF_CRTSCTS); ttstat.tt_flags |= TF_OUT_OF_BAND; /* we always want OUT_OF_BAND */ /* Convert from POSIX to MACH speed */ if ((cflag & CBAUD) < (sizeof(baud_table)/sizeof(baud_table[0]))) ttstat.tt_ispeed = ttstat.tt_ospeed = baud_table[cflag & CBAUD]; else /* Largest possible baud rate (for the moment) */ ttstat.tt_ispeed = ttstat.tt_ospeed = 230400; if (cflag & CRTSCTS) { info->flags |= ASYNC_CTS_FLOW; } else info->flags &= ~ASYNC_CTS_FLOW; if (cflag & CLOCAL) info->flags &= ~ASYNC_CHECK_CD; else { info->flags |= ASYNC_CHECK_CD; } #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) if (I_INPCK(info->tty)) info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) info->read_status_mask |= UART_LSR_BI; info->ignore_status_mask = 0; if (I_IGNPAR(info->tty)) { info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; info->read_status_mask |= UART_LSR_PE | UART_LSR_FE; } if (I_IGNBRK(info->tty)) { info->ignore_status_mask |= UART_LSR_BI; info->read_status_mask |= UART_LSR_BI; /* * If we're ignore parity and break indicators, ignore * overruns too. (For real raw support). */ if (I_IGNPAR(info->tty)) { info->ignore_status_mask |= UART_LSR_OE; info->read_status_mask |= UART_LSR_OE; } } if (cflag & PARENB) { ttstat.tt_flags |= TF_INPCK; ttstat.tt_flags |= (cflag & PARODD) ? TF_ODDP : TF_EVENP; } if ((cflag & CSIZE) != CS7) { /* assume CS8 */ ttstat.tt_flags |= TF_LITOUT | TF_8BIT; } if (cflag & CLOCAL) ttstat.tt_flags |= TF_NOHANG; if (cflag & CREAD) ttstat.tt_flags |= TF_READ; if (cflag & HUPCL) ttstat.tt_flags |= TF_HUPCLS; if (cflag & CRTSCTS) ttstat.tt_flags |= TF_CRTSCTS; if (device_port != MACH_PORT_NULL) { kr = device_set_status(device_port, TTY_STATUS_NEW, (dev_status_t) &ttstat, ttstat_count); if (kr != D_SUCCESS) { MACH3_DEBUG(1, kr, ("change_speed(dev 0x%x): " "device_set_status(TTY_STATUS_NEW)", info->tty->device)); } } }
/* * This routine is called whenever a serial port is opened. It * enables interrupts for a serial port, linking in its async structure into * the IRQ chain. It also performs the serial-specific * initialization for the tty structure. */ int rs_open(struct tty_struct *tty, struct file * filp) { struct async_struct *info; int retval, line; line = MINOR(tty->device) - tty->driver.minor_start; if ((line < 0) || (line >= NR_PORTS)) return -ENODEV; info = rs_table + line; if (serial_paranoia_check(info, tty->device, "rs_open")) return -ENODEV; #ifdef SERIAL_DEBUG_OPEN printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, info->count); #endif if (!(info->flags & ASYNC_INITIALIZED)) { char device_name[25]; mach_port_t device_port; dev_mode_t device_mode; kern_return_t kr; int word, count; sprintf(device_name, "com%d", line); device_mode = D_READ | D_WRITE; kr = device_open(device_server_port, MACH_PORT_NULL, device_mode, server_security_token, device_name, &device_port); if (kr != D_SUCCESS) { if (kr != D_NO_SUCH_DEVICE) { MACH3_DEBUG(2, kr, ("rs_open(dev 0x%x): " "device_open(\"%s\")", tty->device, device_name)); } return -ENODEV; } info->flags &= ~ASYNC_DCD_PRESENT; count = TTY_MODEM_COUNT; kr = device_get_status(device_port, TTY_MODEM, &word, &count); if (kr == D_SUCCESS && (word & TM_CAR) != 0) info->flags |= ASYNC_DCD_PRESENT; else info->flags &= ~ASYNC_DCD_PRESENT; /* Flush any garbage data which might be left over.. */ count = TTY_FLUSH_COUNT; word = D_READ|D_WRITE; kr = device_set_status(device_port, TTY_FLUSH, &word, count); info->device_port = device_port; tty->flip.char_buf_ptr = tty->flip.char_buf; tty->flip.flag_buf_ptr = tty->flip.flag_buf; tty->flip.count = 0; /* Now register a few asynchronous routines.. */ device_reply_register(&info->reply_port, (char *) info, serial_read_reply, serial_write_reply); } ASSERT(MACH_PORT_VALID(info->device_port)); info->count++; tty->driver_data = info; info->tty = tty; /* * Start up serial port */ retval = startup(info); if (retval) return retval; if (info->count == 1) server_thread_start(serial_read_thread, (void *) line); retval = block_til_ready(tty, filp, info); if (retval) { #ifdef SERIAL_DEBUG_OPEN printk("rs_open returning after block_til_ready with %d\n", retval); #endif return retval; } if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { if (tty->driver.subtype == SERIAL_TYPE_NORMAL) *tty->termios = info->normal_termios; else *tty->termios = info->callout_termios; change_speed(info); } info->session = current->session; info->pgrp = current->pgrp; #ifdef SERIAL_DEBUG_OPEN printk("rs_open ttys%d successful...", info->line); #endif return 0; }