Merge from vendor branch GCC:
[dragonfly.git] / sys / dev / atm / hfa / fore_stats.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
8  * This Host ATM Research Platform ("HARP") file (the "Software") is
9  * made available by Network Computing Services, Inc. ("NetworkCS")
10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
11  * support of any kind.
12  *
13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17  * In no event shall NetworkCS be responsible for any damages, including
18  * but not limited to consequential damages, arising from or relating to
19  * any use of the Software or related support.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/sys/dev/hfa/fore_stats.c,v 1.4 1999/08/28 00:41:52 peter Exp $
27  *      @(#) $DragonFly: src/sys/dev/atm/hfa/fore_stats.c,v 1.6 2005/02/01 00:51:50 joerg Exp $
28  */
29
30 /*
31  * FORE Systems 200-Series Adapter Support
32  * ---------------------------------------
33  *
34  * Device statistics routines
35  *
36  */
37
38 #include "fore_include.h"
39
40 /*
41  * Get device statistics from CP
42  * 
43  * This function will issue a GET_STATS command to the CP in order to
44  * initiate the DMA transfer of the CP's statistics structure to the host.
45  * We will then sleep pending command completion.  This must only be called
46  * from the ioctl system call handler.
47  *
48  * Called at splnet.
49  *
50  * Arguments:
51  *      fup     pointer to device unit structure
52  *
53  * Returns:
54  *      0       stats retrieval successful
55  *      errno   stats retrieval failed - reason indicated
56  *
57  */
58 int
59 fore_get_stats(fup)
60         Fore_unit       *fup;
61 {
62         H_cmd_queue     *hcp;
63         Cmd_queue       *cqp;
64         int             s, sst;
65
66         ATM_DEBUG1("fore_get_stats: fup=%p\n", fup);
67
68         /*
69          * Make sure device has been initialized
70          */
71         if ((fup->fu_flags & CUF_INITED) == 0) {
72                 return (EIO);
73         }
74
75         /*
76          * If someone has already initiated a stats request, we'll
77          * just wait for that one to complete
78          */
79         s = splimp();
80         if (fup->fu_flags & FUF_STATCMD) {
81
82                 sst = tsleep((caddr_t)&fup->fu_stats, PCATCH, "fore", 0);
83                 (void) splx(s);
84                 return (sst ? sst : fup->fu_stats_ret);
85         }
86
87         /*
88          * Limit stats gathering to once a second or so
89          */
90         if (time_second == fup->fu_stats_time) {
91                 (void) splx(s);
92                 return (0);
93         } else
94                 fup->fu_stats_time = time_second;
95
96         /*
97          * Queue command at end of command queue
98          */
99         hcp = fup->fu_cmd_tail;
100         if ((*hcp->hcq_status) & QSTAT_FREE) {
101                 void    *dma;
102
103                 /*
104                  * Queue entry available, so set our view of things up
105                  */
106                 hcp->hcq_code = CMD_GET_STATS;
107                 hcp->hcq_arg = NULL;
108                 fup->fu_cmd_tail = hcp->hcq_next;
109
110                 /*
111                  * Now set the CP-resident queue entry - the CP will grab
112                  * the command when the op-code is set.
113                  */
114                 cqp = hcp->hcq_cpelem;
115                 (*hcp->hcq_status) = QSTAT_PENDING;
116
117                 dma = DMA_GET_ADDR(fup->fu_stats, sizeof(Fore_cp_stats),
118                         FORE_STATS_ALIGN, 0);
119                 if (dma == NULL) {
120                         fup->fu_stats->st_drv.drv_cm_nodma++;
121                         (void) splx(s);
122                         return (EIO);
123                 }
124                 fup->fu_statsd = dma;
125                 cqp->cmdq_stats.stats_buffer = (CP_dma) CP_WRITE(dma);
126
127                 fup->fu_flags |= FUF_STATCMD;
128                 cqp->cmdq_stats.stats_cmd = 
129                         CP_WRITE(CMD_GET_STATS | CMD_INTR_REQ);
130
131                 /*
132                  * Now wait for command to finish
133                  */
134                 sst = tsleep((caddr_t)&fup->fu_stats, PCATCH, "fore", 0);
135                 (void) splx(s);
136                 return (sst ? sst : fup->fu_stats_ret);
137
138         } else {
139                 /*
140                  * Command queue full
141                  */
142                 fup->fu_stats->st_drv.drv_cm_full++;
143                 (void) splx(s);
144                 return (EIO);
145         }
146 }
147