e1_input: add 'port_nr' field and support DAHDI T1 cards

the "e1_line <0-255> port <0-255>" vty command allows the user to
set which physical port/card number should be represented by the
given virtual e1_line.

Furthermore, we now actually query the DAHDI hardware to determine the
number of ports of a given span (e.g. only 24 in case of T1) instead of
blindly assuming there are 31 timeslots on each port.

This specifically will fix T1 timeslot (/dev/dahdi/%u) calculation in
setups with multiple DAHDI spans/ports and a T1 span != span 1.
diff --git a/src/e1_input_vty.c b/src/e1_input_vty.c
index bcc0251..10c4687 100644
--- a/src/e1_input_vty.c
+++ b/src/e1_input_vty.c
@@ -69,6 +69,25 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_e1line_port, cfg_e1_line_port_cmd,
+	"e1_line <0-255> port <0-255>"
+	E1_LINE_HELP, "Set physical port/span/card number\n"
+	"E1/T1 Port/Span/Card number\n")
+{
+	struct e1inp_line *line;
+	int e1_nr = atoi(argv[0]);
+
+	line = e1inp_line_find(e1_nr);
+	if (!line) {
+		vty_out(vty, "%% Line %d doesn't exist%s", e1_nr, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	line->port_nr = atoi(argv[1]);
+
+	return CMD_SUCCESS;
+}
+
 DEFUN(cfg_e1line_name, cfg_e1_line_name_cmd,
 	"e1_line <0-255> name .LINE",
 	E1_LINE_HELP "Set name for this line\n" "Human readable name\n")
@@ -111,6 +130,8 @@
 	llist_for_each_entry(line, &e1inp_line_list, list) {
 		vty_out(vty, " e1_line %u driver %s%s", line->num,
 			line->driver->name, VTY_NEWLINE);
+		vty_out(vty, " e1_line %u port %u%s", line->num,
+			line->port_nr, VTY_NEWLINE);
 		if (line->name)
 			vty_out(vty, " e1_line %u name %s%s", line->num,
 				line->name, VTY_NEWLINE);
@@ -200,7 +221,7 @@
 
 	if (argc == 0) {
 		llist_for_each_entry(line, &e1inp_line_list, list) {
-			for (ts_nr = 0; ts_nr < NUM_E1_TS; ts_nr++) {
+			for (ts_nr = 0; ts_nr < line->num_ts; ts_nr++) {
 				ts = &line->ts[ts_nr];
 				e1ts_dump_vty(vty, ts);
 			}
@@ -224,7 +245,7 @@
 	}
 	if (argc >= 2) {
 		ts_nr = atoi(argv[1]);
-		if (ts_nr >= NUM_E1_TS) {
+		if (ts_nr >= line->num_ts) {
 			vty_out(vty, "E1 timeslot %s is invalid%s",
 				argv[1], VTY_NEWLINE);
 			return CMD_WARNING;
@@ -233,7 +254,7 @@
 		e1ts_dump_vty(vty, ts);
 		return CMD_SUCCESS;
 	} else {
-		for (ts_nr = 0; ts_nr < NUM_E1_TS; ts_nr++) {
+		for (ts_nr = 0; ts_nr < line->num_ts; ts_nr++) {
 			ts = &line->ts[ts_nr];
 			e1ts_dump_vty(vty, ts);
 		}
@@ -254,6 +275,7 @@
 	install_element(CONFIG_NODE, &cfg_e1inp_cmd);
 	install_node(&e1inp_node, e1inp_config_write);
 	install_element(L_E1INP_NODE, &cfg_e1_line_driver_cmd);
+	install_element(L_E1INP_NODE, &cfg_e1_line_port_cmd);
 	install_element(L_E1INP_NODE, &cfg_e1_line_name_cmd);
 
 	install_element_ve(&show_e1drv_cmd);